Czysto wirtualny destruktor powoduje błąd linkera

0

Witam,

Deklaracja czysto wirtualnego destruktora w klasie bazowej powoduje błąd kompilatora, który nie występuje gdy zamiast destruktora czysto wirtualnego wstawiam destruktor z pustym ciałem. Jednakże chcąc trzymać się polecenia w zadaniu szukam rozwiązania, dzięki któremu program będzie działał z wyżej wspomnianym czysto wirtualnym destruktorem. Byłbym bardzo wdzięczny, gdyby ktoś pomógł mi w rozwiązaniu tego problemu.

Kod: http://pastebin.com/7EJ9TCAF

3

Możesz zdefiniować funkcję wirtualną, która jest zadeklarowana jako =0. Zrób to.

0

Destruktor wirtualny musi posiadać definicję. Dodaj jego definicję, lub zapisz go tak:

virtual ~abstr_emp() = 0 {}
3

Dodaj ciało do destruktora czysto wirtualnego.

class abstr_emp
{
    virtual ~abstr_emp() = 0;
};
abstr_emp::~abstr_emp() = default;

abstr_emp::~abstr_emp() {}       // jesli nie masz C++1x
0

Nie wiem, czy dobrze rozumuje, ale wywołując konstruktor abstrakcyjnej klasy bazowej w jednej z klas pochodnych muszę zdefiniować ciało destruktora poza klasą, nawet jeśli jest on czysto wirtualny? W sytuacji, gdy ww. konstruktor nie byłby wywołany wystarczyłby taki zapis: virtual ~destruktor() = 0;?

0

Nie, możesz zapisać to tak:

class destructor{
virtual ~destruktor(){}
};
 

Masz puste ciało, chodzi głównie o to, aby destruktory z klas dziedziczących wywoływały się.

2

Jeżeli zamierzasz stworzyć obiekt klasy pochodnej to destruktor musi mieć implementację, bo będzie wywołany gdy obiekt klasy pochodnej zostanie zniszczony. W przypadku destruktora czysto wirtualnego ta implementacja jest poza klasą tylko dlatego, że nie istnieje zapis pozwalający na zdefiniowanie w klasie. Jeśli destruktor jest tylko wirtualny (a nie czysto) to jak najbardziej można zdefiniować jego ciało w klasie.

8

@twonek @vpiotr @mwl4:
Konstruktor (destruktor) jest "funkcją o nazwie takiej jak nazwa klasy". Zatem http://melpon.org/wandbox/permlink/9MkXkGYC1glvoNvj jest "najbardziej poprawne". Dlaczego?
foo to class template. class template nie jest klasą. Klasą (typem) jest foo<int>. Stąd też konstruktor nazywa się foo<int>.

Dlaczego zatem http://melpon.org/wandbox/permlink/ISwFsqsiLaRahThB działa?
Ficzer nazywa się class name injection. Działa podobnie jakby w klasie foo znajdował się member foo wskazujący na *this.
http://melpon.org/wandbox/permlink/8zpGWdPsUui2SHiX
linie 6, 13: typ foo<int>::foo okazuje się być tym samym co foo<int>
linia 7: foo to injected class name, to samo co typ naszej klasy, czyli foo<int>
linia 8: podoba sytuacja. Zwracamy *this i bindujemy to do foo. Działa, chociaż *this jest typu foo<int>

C++11 9.2: A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.
The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name. A
class-specifier is commonly referred to as a class definition. A class is considered defined after the closing
brace of its class-specifier has been seen even though its member functions are in general not yet defined.
The optional attribute-specifier-seq appertains to the class; the attributes in the attribute-specifier-seq are
thereafter considered attributes of the class whenever it is named.

Działa nawet w bardzo pokręconych przepadkach: http://melpon.org/wandbox/permlink/vbQ7fDiIJkmgn21E

1 użytkowników online, w tym zalogowanych: 0, gości: 1