2009-06-10 9 views
28

W C++ jest to legalne dać implementację czystej funkcji wirtualnej:W jakich okolicznościach warto wdrożyć czysto wirtualną funkcję?

class C 
{ 
public: 
    virtual int f() = 0; 
}; 

int C::f() 
{ 
    return 0; 
} 

Dlaczego byś kiedykolwiek chcesz to zrobić?

Powiązane Pytanie: C++ faq lite zawiera przykład:

class Funct { 
public: 
    virtual int doit(int x) = 0; 
    virtual ~Funct() = 0; 
}; 

inline Funct::~Funct() { } // defined even though it's pure virtual; it's faster this way; trust me 

ja nie rozumiem, dlaczego destruktor jest zadeklarowana czysto wirtualne, a następnie wdrożone; i nie rozumiem komentarza, dlaczego to powinno być szybsze.

Odpowiedz

23

Zadeklarowane destruktory zawsze muszą być implementowane, ponieważ implementacja wywoła je jako część destrukcji obiektu pochodnego.

Inne czyste funkcje wirtualne mogą zostać zaimplementowane, jeśli zapewniają użyteczną wspólną funkcję, ale zawsze muszą być wyspecjalizowane. W przypadku, zwykle pochodzące implementacje klasy uczyni wyraźne wezwanie do wykonania podstawy:

void Derived::f() 
{ 
    Base::f(); 

    // Other Derived specific functionality 
} 

Zazwyczaj dokonać destruktor wirtualny jeśli trzeba dokonać abstrakcyjnej klasy (czyli zapobiegać niż pochodzące przypadkach od tworzony), ale klasa nie ma innych funkcji, które są naturalnie czyste wirtualne. Myślę, że "zaufaj mi, że jest to szybsze" odnosi się do faktu, że ponieważ destruktory wywoływane jako część oczyszczonego obiektu pochodnego nie muszą używać mechanizmu odnośnika, można wykorzystać implementację inline, w przeciwieństwie do typowych wywołań funkcji wirtualnych .

4

Jeśli masz tak powszechną funkcjonalność, z której może korzystać klasa pochodna. Ale oni potrzebują wykonać inną pracę, no cóż.

więc klasa pochodna realizuje funkcję wirtualnego i wywołuje podstawowej wersji Base:

class X: public C 
{ 
    public: 
     virtual int f() 
     { 
      return C::f() + 1; // I am +1 over my parent. 
     } 
}; 
0

Bo to uznać za źle uformowane napisać:

class Funct { 
public: 
    virtual int doit(int x) = 0; 
    virtual ~Funct() = 0 {}; 
}; 

Destruktor nadal będzie nazywany jeśli ciebie wywodzą się z tej klasy. Deklarowanie wszystkich metod czystych wirtualnych jest po prostu dla jasności. Równie dobrze możesz napisać tak:

class Funct { 
public: 
    virtual int doit(int x) = 0; 
    virtual ~Funct() {}; 
}; 

Klasa będzie nadal abstrakcyjna, ponieważ co najmniej jedna metoda jest czysto wirtualna. Destruktor nadal jest wbudowany.

2

G'day,

chodzi o zapewnienie realizacji domyślnej funkcji członka zadeklarowana w klasie bazowej, jedynym powodem mogę myśleć w tej chwili jest tam, gdzie chcesz, aby zapewnić realizację domyślną zachowanie jako możliwy wybór wdrożenia dla kogoś, kto specjalizuje się w klasie bazowej.

Autor klasy pochodnej może wybrać domyślną implementację udostępnioną przez autora klasy podstawowej zamiast dodawać własną, wyspecjalizowaną implementację.

Dzieje się tak na ogół wtedy, gdy ludzie sprzeciwiają się posiadaniu oddzielnych funkcji, aby zapewnić interfejs i domyślną implementację zachowania, ale nadal chcą separacji między domyślną implementacją i powiązanym interfejsem.

Ah, właśnie widziałem post @Martin York, który stanowi przykład.

W rzeczywistości Scott Meyers omawia to w swojej książce "Effective C++". Jest to pozycja 36 w 1. edycji.

HTH

okrzyki,

0

Jeśli chodzi o prędkość wirtualnego destruktora, to dlatego, że destruktor jest zdefiniowany w pliku cpp, a nie w nagłówku. Ma więcej wspólnego z rozmiarem niż z prędkością. Wyjaśniono to szczegółowo w "Projektowanie oprogramowania w dużej skali w C++". Niestety nie pamiętam wszystkich szczegółów, ale myślę, że wbudowane funkcje wirtualne są definiowane wiele razy w vtable.

Jest to dyskusja tutaj: Are inline virtual functions really a non-sense?

Powiązane problemy