2010-04-19 11 views
10

Mam pytanie, tutaj są dwie klasy poniżej:Zachowanie funkcji wirtualnych w C++

class Base{ 
     public: 
      virtual void toString();  // generic implementation 
    } 

    class Derive : public Base{ 
     public: 
      (virtual) void toString(); // specific implementation 
    } 

pytanie brzmi:

  • Jeśli chcę podklasą klasy Derive wykonywać polymophism korzystania wskaźnik typu Base, czy słowo kluczowe w nawiasie jest niezbędne?

  • Jeśli odpowiedź brzmi nie, jaka jest różnica między funkcji członka toString klasy Wyprowadź zi bez wirtualny?

+1

Jest to opcjonalne, ale niektórzy uważają za kwestię dobrego stylu wyrażenie wyraźnych informacji o nadpisywaniu funkcji członka. – pmr

Odpowiedz

13

C++ 03 §10.3/2:

Jeżeli wirtualne funkcja element VF uznane w bazową, w klasy pochodnych, pochodzący, bezpośrednio lub pośrednio, z podstawy, człon funkcja VF nazwie i samego lista parametrów jako Base :: vf jest oznaczona , następnie Pochodna :: vf jest również wirtualna (niezależnie od tego, czy jest tak zadeklarowana) i zastępuje Base :: vf.

+2

+1 do cytowania rzeczywistego odniesienia –

10

To słowo kluczowe jest całkowicie opcjonalne i nie ma żadnej różnicy. Właściwość

+11

Nie ma znaczenia dla kompilatora. Dla ludzkiego czytelnika może to faktycznie poprawić czytelność. Zawsze jawnie mówię o stanie wirtualnym na wszystkich poziomach dziedziczenia. –

7

Właściwość virtual jest dziedziczona z klasy bazowej i przyjmuje się, że jest obecna, nawet jeśli nie zostanie wpisana.

1

Kompilator zna już słowo kluczowe "virtual" w klasie bazowej, że toString jest metodą wirtualną. Nie trzeba go powtarzać.

+4

Można dodać, że może to mieć wpływ na ludzki czytelnik. – sbi

1

Funkcja raz wirtualny zawsze wirtualny.

W każdym razie, jeśli słowo kluczowe wirtualne nie jest używane w kolejnych klasach, nie uniemożliwia to, aby funkcja/metoda była "wirtualna", tj. Nadpisana. Więc następujące wytyczne mogą pomóc z punktu widzenia-w-rozwoju zespołu: -

  • Jeśli funkcja/metoda ma być nadpisane, zawsze używaj „wirtualne” słowa kluczowego . Jest to szczególnie przydatne w przypadku klas interfejsu/bazy .
  • Jeśli klasa pochodna ma być sub-klasyfikowane dodatkowo explicity podać „wirtualne” kluczowe dla każdego funkcji/metody, które mogą być zamienione na nowe.
  • Jeśli funkcja/metoda w pochodzącej klasie nie ma być sub-klasyfikowane ponownie, a następnie słowo kluczowe „wirtualny” należy skomentował wskazując, że funkcja/metoda została przesłonięta, ale nie ma kolejne klasy, które go zastąpią ponownie: . To oczywiście nie przeszkadza w zmianie klasy pochodnej z klasy , chyba że klasa jest ostateczna (nie można jej uzyskać), ale wskazuje, że metoda ta nie powinna być nadpisywana. Np .: /*virtual*/ void someFunc();
+0

W przypadku "do nadpisania zawsze", można również dodać czysty specyfikator. – Myke

+0

Myślę, że ma być przecinek między "przesłonięty" i "zawsze". tj. "zawsze używaj słowa kluczowego" virtual ", a nie" zawsze zastępuj ". –

+0

@Ben: masz rację, Thnx. – Abhay

0

To nie ma znaczenia do kompilatora tego, czy dostarczać wirtualny słowa kluczowego w wersjach pochodzących z tej funkcji.

Mimo to dobrze jest go dostarczyć, aby każdy, kto patrzył na Twój kod, mógł powiedzieć, że jest to funkcja wirtualna.

0

To kwestia dobrego stylu, a programista wie, co się dzieje. W C++ 0x możesz użyć [[przesłanianie]], aby było bardziej wyraźne i widoczne. Możesz użyć [[base_check]], aby wymusić użycie [[przesłanianie]].

Jeśli nie chcesz lub nie możesz tego zrobić, po prostu użyj wirtualnego słowa kluczowego.

Jeśli wywodzisz się bez wirtualnego toString, a rzucisz instancję Derive z powrotem do Base, wywołanie toString() wywołałoby w rzeczywistości Base toString(), ponieważ o ile wiadomo, jest to instancja Base.

Powiązane problemy