Dynamiczne łączenie klas z bibliotek DLL

dział ogólny

Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez rafalskraba » czwartek, 4 lutego 2010, 02:10

Witam. Poprzedni mój wątek dotyczył dostępu do klas zapisanych w bibliotekach dll przy pomocy dołączania statycznego. Idąc dalej za ciosem pojawił się problem z dynamicznym dostępem do klas w dll.
Przykladowa klasa:
1. plik *.h biblioteki dll
Kod: Zaznacz cały
class __declspec(dllexport) TKlasa
{
   private:

   public:
      TKlasa();
      ~TKlasa();
      AnsiString pokaz();
};

2. Plik *.cpp biblioteki dll
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#include "klasa.h"
#pragma hdrstop
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

#pragma argsused

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   return 1;
}
//---------------------------------------------------------------------------
TKlasa::TKlasa()
{
   ShowMessage("Konstruktor klasy");
}
TKlasa::~TKlasa()
{
   ShowMessage("Destruktor klasy");
}
AnsiString TKlasa::pokaz()
{
   AnsiString napis;
   napis = "Funkcja z klasy";

   return napis;
}


Jak uzyskać dynamicznie dostęp do metod w/w klasy. Próbowałem czegoś takiego ale mi nic nie wychodziło:
Kod: Zaznacz cały
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "klasa.h"

...
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   HINSTANCE sciezka = LoadLibrary("klasa.dll");
   if(sciezka!=NULL)
   {
      ShowMessage("Zaladowano bibliotekę dll");

      typedef (*klasa1)(); // -> przypuszczam że w tym miejscu jest bład
      klasa1 TKlasa;
      TKlasa = (klasa1)GetProcAddress(sciezka,"_TKlasa");



   }
   else
   {
      ShowMessage("Nie załadowano biblioteki dll");
   }
}


Proszę o jakieś wskazówki.
"Jednym z rodzajów szczęśliwości jest zdolność podejmowania dobrych decyzji."

- Platon-
Avatar użytkownika
rafalskraba
Intelektryk
Intelektryk
 
Posty: 122
Dołączył(a): czwartek, 5 marca 2009, 10:20
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: Windows 7 x64
Kompilator: RAD Studio XE2 Update 4 HotFix 1
SKYPE: rafal.skraba
Gadu Gadu: 0
    Windows 7Firefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez polymorphism » czwartek, 4 lutego 2010, 12:33

Kod: Zaznacz cały
typedef (*klasa1)(); // -> przypuszczam że w tym miejscu jest bład

Dokładnie. To taki prawie wskaźnik na funkcję ;) GetProcAddress, jak sama nazwa wskazuje, zwraca adres funkcji eksportowanej przez bibliotekę. Ty próbujesz pobrać tą funkcją adres klasy! A przecież w innym wątku pisałem, że definicja klasy nie jest eksportowana, bo nie jest czymś, co istnieje w pamięci, to tylko opis, który jest niezbędny kompilatorowi (i Tobie) podczas kompilacji kodu, nic więcej.

Żeby móc korzystać z klasy, którą eksportuje DLL-ka załadowana dynamicznie, musisz jej metody zrobić wirtualnymi. Nie będę wnikał dlaczego tak musi być, odsyłam do jakiejś sensownej literatury (interfejsy, klasa abstrakcyjna, metody wirtualne, vtable). Musisz także zrobić jakąś funkcję, która będzie tworzyć instancję takiej klasy, a także jakiś sensowny mechanizm usuwania jej. Niedawno był temat pisania wtyczek, dałem tam przykład, który powinien Ciebie zainteresować.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez rafalskraba » niedziela, 14 lutego 2010, 20:03

Przerobiłem całkowicie klasę w bibliotece. Teraz ona wygląda następująco:
plik: *.h
Kod: Zaznacz cały
class TSuma
{
   private:
      int a;
   public:
      TSuma();
          double virtual dodawanie(int,int);
      virtual ~TSuma();

};

Plik *.cpp
Kod: Zaznacz cały
TSuma::TSuma()
{

}
TSuma::~TSuma()
{

}
double TSuma::dodawanie(int a, int b)
{
    return (a+b);
}

Export funkcji z biblioteki dll
Kod: Zaznacz cały
extern "C" __declspec(dllexport) TSuma* Test()
{
   return new TSuma();
}

Biblioteka wraz z funkcją jest dołączona do programu i działa poprawanie
Kod: Zaznacz cały
        typedef TSuma* (*Test2)();

   HINSTANCE sciezka;
   sciezka = LoadLibrary("suma.dll");
   if(sciezka == NULL)
   {
      ShowMessage("Brak biblioteki DLL");
      return;
   }
   Test2 przyklad=(Test2)GetProcAddress(sciezka,"_Test");
   if(!przyklad)
   {
   ShowMessage("Nie znaleziono funkcji");
   return;

   }
        int A,B;
   TSuma* suma;
   suma = (przyklad)();
   suma->dodawanie(A,B);
        delete suma; // nie działa poprawnie

Nie chce poprawnie działać funkcja delete tzn nie można skompilować programu, kompilator wypisuje błąd:

nresolved external 'TSuma::~TSuma()' referenced from ...

Avatar użytkownika
rafalskraba
Intelektryk
Intelektryk
 
Posty: 122
Dołączył(a): czwartek, 5 marca 2009, 10:20
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: Windows 7 x64
Kompilator: RAD Studio XE2 Update 4 HotFix 1
SKYPE: rafal.skraba
Gadu Gadu: 0
    Windows 7Firefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez polymorphism » niedziela, 14 lutego 2010, 23:25

Powinno być tak, jak w wątku o pisaniu wtyczek. Czyli musisz zdefiniować interfejs, który będzie pośredniczył pomiędzy aplikacją a biblioteką. Teraz kompilator szuka implementacji destruktora zdefiniowanego (pośrednio lub bezpośrednio) wewnątrz aplikacji, a tej z wiadomych względów nie ma. Z drugiej strony, żeby taki numer przeszedł, destruktor musiałby być czysto wirtualnym destruktorem, ale takie w C++ nie występują.

Następna rzecz to zarządzanie pamięcią, pisałem już o tym. Jeśli DLL-ka przydziela jakąś pamięć, to i ona musi ją zwolnić, szczególnie gdy używasz do (de)alokacji funkcji biblioteki standardowej (vide metoda IPlugin::Destroy).

Przejrzyj jeszcze raz tamten wątek. Dobrze by było, jakbyś zrobił to posiłkując się jakąś dobrą książką wprowadzającą do programowania obiektowego w C++.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez Witold » poniedziałek, 15 lutego 2010, 12:11

polymorphism napisał(a):Teraz kompilator szuka implementacji destruktora zdefiniowanego (pośrednio lub bezpośrednio) wewnątrz aplikacji, a tej z wiadomych względów nie ma.


Ale dlaczego znajduje TSuma::dodawanie(int a, int b) a destruktora ~TSuma() już nie ?

polymorphism napisał(a):Z drugiej strony, żeby taki numer przeszedł, destruktor musiałby być czysto wirtualnym destruktorem, ale takie w C++ nie występują.


Na stronach podanych niżej są opisy/kody z destruktorami czysto wirtualnymi, co prawda destruktor musi być raczej zdefiniowany... ;)
http://stackoverflow.com/questions/6309 ... uctor-in-c
http://www.gotw.ca/gotw/031.htm

12.4 Destructors

6 A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    AmigaAWeb

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez polymorphism » poniedziałek, 15 lutego 2010, 14:32

Ale dlaczego znajduje TSuma::dodawanie(int a, int b) a destruktora ~TSuma() już nie ?

Hmm, tego nie wiem, choć podejrzewam, że ma to związek z kompilatorem, jego reakcją na tego typu rzeczy. W VC ten kod:
Kod: Zaznacz cały
class base
{
public:
   virtual ~base();
};

...

base* x = NULL;
delete x;

kompiluje się bez problemu.

Na stronach podanych niżej są opisy/kody z destruktorami czysto wirtualnymi, co prawda destruktor musi być raczej zdefiniowany... ;)

No faktycznie, można. Zawsze mi się wydawało, że czysto wirtualnych destruktorów nie ma, wszak z definicji nie można ich podmieniać, w przeciwieństwie do metod wirtualnych. Choć ten wymóg zapewnienia definicji takiego destruktora wskazuje, że nie do końca jest on pure virtual. No ale nieważne, C++ człowiek uczy się całe życie... 8-)
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez Witold » wtorek, 16 lutego 2010, 10:28

Dzięki za odpowiedź.

polymorphism napisał(a):W VC ten kod /.../ kompiluje się bez problemu.


Pod BCB6 nie: [Linker Error] Unresolved external 'base::~base()' ….
Pod VC ma to coś wspólnego z optymalizacją ? Dla base* x = (base*)1;lub volatile base* x = NULL; też się uda ?

Wydaje mi się że metoda/destruktor jest pure virtual gdy jest oznaczona/y =0, bez znaczenia czy ma ciało czy nie.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    AmigaAWeb

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez polymorphism » wtorek, 16 lutego 2010, 11:24

Pod VC ma to coś wspólnego z optymalizacją ?

Nie, testowałem w wersji debug. Na 100% wywołuje domyślny destruktor.

Dla base* x = (base*)1;lub volatile base* x = NULL; też się uda ?

To, jaką wartość przyjmie x, nie ma aż takiego znaczenia, wszak chodzi o znalezienie odpowiedniego destruktora tudzież reakcji kompilatora na jego niekompletną definicję. I jak widać, jest to zależne od kompilatora.

Wydaje mi się że metoda/destruktor jest pure virtual gdy jest oznaczona/y =0, bez znaczenia czy ma ciało czy nie.

W przypadku destruktorów owszem, ale w przypadku metod to IMO bez sensu. Bo co z tego, że metoda ma ciało, jeśli to zero powoduje, że i tak musisz w którejś tam klasie pochodnej zapewnić jej nową, tą właściwą implementację? Nie wiem, być może standard na to pozwala, ale jak ja się uczyłem, zasada była prosta: metoda czysto wirtualna to brak implementacji, co powodowało że klasa z automatu stawała się klasą abstrakcyjną, a co za tym idzie instancji tej klasy tworzyć nie można.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez Cyfrowy Baron » wtorek, 16 lutego 2010, 12:16

Problem stanowi nie tylko wywołanie destruktora, ale również konstruktora i nie jest to zależne od tego, czy klasa znajduje się w bibliotece DLL, czy nie.
Dołączam do projektu plik suma.h zawierający deklarację klasy TSuma, towarzyszy mu oczywiście plik suma.cpp, konstrukcja plików dokładnie taka jaka podał rafalskraba. Próbuję utworzyć nowy obiekt klasy:

Kod: Zaznacz cały
TSuma* suma = new TSuma();
suma->dodawanie(10, 10);
delete suma;


[ILINK32 Error] Error: Unresolved external 'TSuma::~TSuma()' referenced from D:\EMBARCADERO_PROJECT_2010\Project1\UNIT1.OBJ
[ILINK32 Error] Error: Unresolved external 'TSuma::TSuma()' referenced from D:\EMBARCADERO_PROJECT_2010\Project1\UNIT1.OBJ




Po wprowadzeniu drobnych modyfikacji, kod działa:

klasa TSuma
plik suma.h
Kod: Zaznacz cały
class TSuma
{
  private:
         int a;
  public:
        TSuma();
        virtual ~TSuma();

        double virtual dodawanie(int,int);
};


plik suma.cpp
Kod: Zaznacz cały
#include "suma.h"

TSuma::TSuma()
{

}
TSuma::~TSuma()
{

}
double TSuma::dodawanie(int a, int b)
{
        return (a + b);
}


Do projektu aplikacji w której będzie podłączana biblioteka dodajemy plik źródłowy suma.cpp poprzez menu Project -> Add to project, a w sekcji include w pliku źródłowym lub nagłówkowych tejże aplikacji dodajemy wpis:

Kod: Zaznacz cały
#include "suma.h"


To oczywiście zakładając, że pliki suma.cpp i suma.h znajdują się w katalogu aplikacji.

Nie tworzyłem biblioteki DLL z klasą, więc nie wiem jak to zadziała, ale podłączanie zgodnie z podanym kodem nie generuje żadnych błędów, czyli tego nie zmieniałem:

Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
typedef TSuma* (*Test2)();

HINSTANCE sciezka;
sciezka = LoadLibrary("suma.dll");
if(sciezka == NULL)
{
  ShowMessage("Brak biblioteki DLL");
  return;
}
Test2 przyklad=(Test2)GetProcAddress(sciezka,"_Test");
if(!przyklad)
{
  ShowMessage("Nie znaleziono funkcji");
  return;

}
int A,B;
TSuma* suma;
suma = (przyklad)();
suma->dodawanie(A, B);
delete suma;  // <-- już działa
}
//---------------------------------------------------------------------------
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez rafalskraba » wtorek, 16 lutego 2010, 12:34

Witaj cyfrowybaronie. Ten kod co podałeś oczywiście będzie działał.
Kod: Zaznacz cały
     TSuma* suma = new TSuma();
    suma->dodawanie(10, 10);
    delete suma;


Ale funkcja delete usuwa ta funkcje TSuma* suma = new TSuma(); . Biblioteka dll oczywiście zostaje załadowana natomiast funkcja z klasy nie jest wywoływana jest ona natomiast wywoływana standartowo.
"Jednym z rodzajów szczęśliwości jest zdolność podejmowania dobrych decyzji."

- Platon-
Avatar użytkownika
rafalskraba
Intelektryk
Intelektryk
 
Posty: 122
Dołączył(a): czwartek, 5 marca 2009, 10:20
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: Windows 7 x64
Kompilator: RAD Studio XE2 Update 4 HotFix 1
SKYPE: rafal.skraba
Gadu Gadu: 0
    Windows 7Firefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez Witold » wtorek, 16 lutego 2010, 12:40

polymorphism napisał(a):Nie, testowałem w wersji debug. Na 100% wywołuje domyślny destruktor.


Nie rozumiem. Obok destruktora virtual ~base(); jest jeszcze ~base(); (bez virtual) ?
Takie coś nie przechodzi:

Kod: Zaznacz cały
class base
{
public:
   virtual ~base();
   ~base();
};


[C++ Error] Unit1.cpp(25): E2238 Multiple declaration for 'base::~base()'
[C++ Error] Unit1.cpp(24): E2344 Earlier declaration of 'base::~base()'



polymorphism napisał(a):W przypadku destruktorów owszem, ale w przypadku metod to IMO bez sensu. Bo co z tego, że metoda ma ciało, jeśli to zero powoduje, że i tak musisz w którejś tam klasie pochodnej zapewnić jej nową, tą właściwą implementację?


W przypadku destruktorów jest chyba podobnie. Wydaje mi się że destruktor dostajesz gratis, dlatego nie musisz się martwić o ich implementację. Z tym że jeżeli mamy klasę pochodną (dla której będzie wywołany destruktor) to ona będzie potrzebowała destruktora klasy bazowej .


Język C++ B. Stroustrup (niestety mam starą wersje książki) napisał(a):Funkcję wirtualną specyfikuje się jako czystą za pomocą czystego specyfikatora w deklaracji funkcji wewnątrz deklaracji klasy. Czystą funkcję trzeba definiować tylko wtedy, gdy wywołuje się ją jawnie z użyciem nazwy kwalifikowanej…
Ostatnio edytowano wtorek, 16 lutego 2010, 12:56 przez Witold, łącznie edytowano 1 raz
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    AmigaAWeb

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez polymorphism » wtorek, 16 lutego 2010, 12:44

Cyfrowy Baron napisał(a):Problem stanowi nie tylko wywołanie destruktora, ale również konstruktora i nie jest to zależne od tego, czy klasa znajduje się w bibliotece DLL, czy nie.

Tak, tylko my nie mówimy tu o statycznym linkowaniu, ale o dynamicznym, gdzie tworzenie obiektów poprzez wywołanie new, czy też lokalnie, na stosie, nie wchodzi w rachubę - od tego ma eksportową funkcję Test.

Przykład, który podałeś jest zupełnie nietrafiony, bo musiałeś po stronie aplikacji zawrzeć całą klasę, włącznie z definicją metod. Czyli DLL-ka ogranicza się jedynie do tworzenia instancji klasy, więc jest zupełnie zbędna, bo to samo mogę zrobić bez niej.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez Cyfrowy Baron » wtorek, 16 lutego 2010, 12:54

Tak też podejrzewałem, że obiekt jest tworzony w oparciu o włączony moduł suma.*, a nie w oparciu o klasę w bibliotece DLL, dlatego zaznaczyłem, że nie testowałem tego z biblioteką DLL. Przeprowadziłem kilka testów, ale zawsze otrzymuję komunikat błędu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez Cyfrowy Baron » wtorek, 16 lutego 2010, 13:03

Temat jest mi raczej obcy, nigdy nie próbowałem umieszczać klasy w bibliotece DLL w taki sposób, ale wydaje mi się, ze problem dotyczy komunikacji między plikami suma.cpp i suma.h.

Załóżmy, że rezygnujemy z pliku suma.cpp i całą klasę zawieramy w pliku suma.h:

Kod: Zaznacz cały
class TSuma
{
       private:
          int a;
       public:

    virtual ~TSuma() { };
    TSuma() { };

    double virtual TSuma::dodawanie(int a, int b)
    {
        return (a + b);
    }

};


Teraz wystarczy w pliku aplikacji w sekcji include włączyć plik #include suma.h. Nie będzie komunikatów błędu, tylko czy to nie jest to samo co z dołączeniem pliku suma.cpp?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne łączenie klas z bibliotek DLL

Nowy postprzez polymorphism » wtorek, 16 lutego 2010, 13:07

Nie rozumiem. Obok destruktora virtual ~base(); jest jeszcze ~base(); (bez virtual) ?

Nie no, przecież każda klasa (teoretycznie) ma swój domyślny destruktor, a dodanie virtual do deklaracji powoduje tylko to, że adres destruktora dopisany jest do vtable klasy. Tak sobie myślę, że sama deklaracja wirtualnego destruktora powoduje, że domyślny konstruktor staje się wirtualny, dzięki czemu destruktory klas pochodnych także. Ale mogę się mylić, nie testowałem...

--- edit ---

Heh, tego się przetestować nie da, bo wyłażą błędy linkera - to samo co w BCB, tyle że przy próbie stworzenia instancji klasy pochodnej.

W przypadku destruktorów jest chyba podobnie.

No właśnie nie, bo nie możesz podmienić klasie bazowej jej konstruktora/destruktora z poziomu klasy pochodnej - właśnie tu jest ta różnica między metodą a destruktorem. Dlatego, tak sądzę, pomimo tej umownej czystej wirtualności powinieneś zapewnić implementację takiemu destruktorowi (o ile chcesz tworzyć instancję tej klasy lub jej pochodnej).
Ostatnio edytowano wtorek, 16 lutego 2010, 13:20 przez polymorphism, łącznie edytowano 1 raz
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości