2015-04-17 12 views
5

Czy kiedykolwiek ma sens zastąpienie czystej wirtualnej metody inną, czystą wirtualną metodą? Czy są jakieś różnice funkcjonalne lub być może powody, dla których styl kodu preferuje jedną z następujących opcji w stosunku do drugiej?C++ przesłonić czystą metodę wirtualną za pomocą czystej wirtualnej metody

class Interface { 
public: 
    virtual int method() = 0; 
}; 

class Abstract : public Interface { 
public: 
    int method() override = 0; 
}; 

class Implementation : public Abstract { 
public: 
    int method() override { return 42; } 
}; 

Versus:

class Interface { 
public: 
    virtual int method() = 0; 
}; 

class Abstract : public Interface {}; 

class Implementation : public Abstract { 
public: 
    int method() override { return 42; } 
}; 
+1

Przekazałby tylko coś komuś czytającemu twój kod. * "Droga osoba, która przegląda mój abstrakcyjny kod ... zauważ, że ta klasa rzeczywiście ma funkcję wirtualną". –

Odpowiedz

4

Oba kody dają ten sam efekt: Klasa Abstract jest abstrakcyjna i nie można jej instancję.

Istnieje jednak różnica znaczeniowa między tymi dwoma postaciami:

  • Pierwszą formą przypomina wyraźnie, że klasa jest abstrakcyjna Abstract (tylko w przypadku, gdy nazwa nie będzie self-sepaking tyle ;-)). Nie tylko to przypomina: zapewnia to również, upewniając się, że ta metoda jest czysto wirtualna.
  • Druga forma oznacza, że ​​klasa Abstract dziedziczy wszystko dokładnie od Interface. Jest abstrakcyjny wtedy i tylko wtedy, gdy jest to klasa podstawowa.

To ma wpływ na przyszłe zmiany w Twoim kodzie. Na przykład, jeśli kiedyś zmienisz zdanie i chcą współpracować mieć domyślną implementację dla method():

  • W pierwszej postaci Absract pozostaje abstrakcyjny i nie posiądą domyślną implementację metody.
  • Drugi formularz zapewnia, że ​​Abstact będzie nadal dziedziczyć i zachowywać się dokładnie tak, jak Interface.

Osobiście uważam, że druga forma jest bardziej intuicyjna i zapewnia lepszy rozdział obaw. Ale mogę sobie wyobrazić, że mogą istnieć pewne sytuacje, w których pierwsza forma mogłaby mieć sens.

4

Czysta specyfikacja metody wymusza przesłonięcie, ale nie uniemożliwia realizacji metody. Oto rzadka, ale czasami przydatna technika.

class Interface 
{ 
    virtual void method() = 0; 
}; 

class Abstract : public Interface 
{ 
    virtual void method() = 0; 
} 
inline void Abstract::method() 
{ 
    do something interesting here; 
} 

class Concrete : public Abstract 
{ 
    virtual void method(); 
} 

inline void Concrete::method() 
{ 
    // let Abstract::method() do it's thing first 
    Abstract::method(); 
    now do something else interesting here; 
} 

To jest czasami przydatne, gdy istnieje kilka rodzajów pochodzące od abstrakcji, które potrzebują wspólną funkcjonalność, ale też trzeba dodać specyficzne zachowanie klasy. [i powinien być zmuszony do zapewnienia tego zachowania.]

+1

Zauważ, że 'inline' jest po prostu po to, aby kod miał sens, gdyby wszystko pojawiło się w nagłówku. W praktyce prawdopodobnie powinieneś unikać wbudowanych wirtualnych metod! –

Powiązane problemy