2010-10-10 13 views
9

Załóżmy mam dwie klasy:domyślny wirtualny d'tor

class Base{}; 

class Derived: public Base{}; 

nikt nie ma d'Tor, w tym przypadku, jeśli Oświadczam o zmiennych:

Base b; 
Derived d; 

mój kompilator będzie produkować dla me d'tors, moje pytanie brzmi, domyślne dydaktyki z b and d będą wirtualne czy nie?

+0

możliwe duplikat [wirtualnych destruktory domyślne C++] (http://stackoverflow.com/questions/827196/virtual-default-destructors-in-c) –

Odpowiedz

10

moje pytanie brzmi, Tors d'z B i D będzie wirtualnym lub nie

Nie, nie będą oni. Jeśli chcesz wirtualnego destruktora, trzeba będzie zdefiniować własną rękę, nawet jeśli jego realizacja jest dokładnie taki sam jak ten, który będzie dostarczany przez kompilator:

class Base { 
    public: 
    virtual ~Base() {} 
}; 
5

moje pytanie jest, Tors d'z B i D będzie wirtualnym lub nie

Krótka odpowiedź: Nopes!

3

NIE będą one wirtualne. Jednakże, jeśli zadeklarowałeś (i zdefiniowałeś) wirtualny dtor w Bazie, to pochodna dtor będzie automatycznie wirtualna. HTH.

6

destruktory z Base i Derived nie będzie virtual . Aby dokonać virtual destruktora trzeba oznaczyć go wyraźnie:

struct Base 
{ 
    virtual ~Base() {} 
}; 

Właściwie nie ma teraz tylko jeden powód, aby korzystać z wirtualnych destruktory. Oznacza to zamknięcie ostrzeżenia gcc: "klasa" Baza "ma funkcje wirtualne, ale nie-wirtualny destruktor". Tak długo, jak zawsze przechowujesz przydzielone obiekty w postaci shared_ptr, naprawdę nie potrzebujesz wirtualnego destruktora. Oto jak:

#include <iostream> // cout, endl 
#include <memory>  // shared_ptr 
#include <string>  // string 

struct Base 
{ 
    virtual std::string GetName() const = 0; 
}; 

class Concrete : public Base 
{ 
    std::string GetName() const 
    { 
     return "Concrete"; 
    } 
}; 

int main() 
{ 
    std::shared_ptr<Base> b(new Concrete); 
    std::cout << b->GetName() << std::endl; 
} 

shared_ptr będzie posprzątać prawidłowo, bez konieczności korzystania z wirtualnego destruktora. Pamiętaj, że musisz będzie trzeba jednak użyć shared_ptr!

Powodzenia!

+1

@Daniel: Naprawdę? Czy shared_ptr będzie poprawnie czyszczone? Czy mógłbyś w tym przypadku zademonstrować, w jaki sposób ten efekt mógłby zostać wdrożony? –

+0

@Armen: The shared_ptr używa własnego destruktora do usunięcia konkretnej instancji. Jest to znane jako RAII w społeczności C++. Moja rada jest taka, że ​​uczysz się wszystkiego co możesz o RAII. Sprawi, że twoje kodowanie w C++ będzie o wiele łatwiejsze, gdy użyjesz RAI we wszystkich sytuacjach. –

+0

@Daniel: Wiem o RAII i wiem również, że ostatecznie destruktor shared_ptr może usunąć zapisane px, gdy pn osiągnie 0. Ale jeśli px miał wskaźnik typu statycznego do Base i wskaźnik typu dynamicznego do Derived, to chyba że Base ma wirtualny destruktor, spowoduje to niezdefiniowane zachowanie. Popraw mnie, jeśli się mylę. –

2

Jak mogą być wirtualne, chyba że wyraźnie uczynić je jako wirtualny

+0

@ powód powód, proszę? –

1

Wystarczy dodać jeszcze jeden przykład na Daniel Lidström's answer

As long as you always store your allocated objects in a shared_ptr, then you really don't need a virtual destructor.

Jeśli ktoś używa shared_ptr tak:

std::shared_ptr<Base> b(new Concrete); 

Następnie destruktor betonu i destruktor bazowy są wywoływane przy zniszczeniu obiektu.

Jeśli ktoś używa shared_ptr tak:

Base* pBase = new Concrete; 
std::shared_ptr<Base> b(pBase); 

Potem tylko destruktor bazowa jest wywoływana na zniszczenie obiektu.

to an example

#include <iostream> // cout, endl 
#include <memory>  // shared_ptr 
#include <string>  // string 

struct Base 
{ 
    virtual std::string GetName() const = 0; 
    ~Base() { std::cout << "~Base\n"; } 
}; 

struct Concrete : public Base 
{ 
    std::string GetName() const 
    { 
     return "Concrete"; 
    } 
    ~Concrete() { std::cout << "~Concrete\n"; } 
}; 

int main() 
{ 
    { 
    std::cout << "test 1\n"; 
    std::shared_ptr<Base> b(new Concrete); 
    std::cout << b->GetName() << std::endl; 
    } 

    { 
    std::cout << "test 2\n"; 
    Base* pBase = new Concrete; 
    std::shared_ptr<Base> b(pBase); 
    std::cout << b->GetName() << std::endl; 
    } 

} 
Powiązane problemy