2010-04-19 3 views
10

Ho una domanda, qui ci sono due classi di seguito:Comportamento della funzione virtuale in C++

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

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

La domanda è:

  • Se voglio sottoclasse di Derive perform polymophism utilizzando un puntatore del tipo Base, la parola chiave virtuale nella parentesi è necessaria?

  • Se la risposta è no, qual è la differenza tra la funzione di membro toString di classe Derivate con e senza virtuale?

+1

È facoltativo, ma alcuni considerano una questione di buon stile essere espliciti riguardo alla sostituzione delle funzioni dei membri. – pmr

risposta

13

C++ 03 §10.3/2:

Se una funzione membro virtual VF è dichiarato in una classe base e in una classe derivata , deriva, direttamente o indirettamente da Base, una funzione membro VF con lo stesso nome e lo stesso elenco parametri come Base :: vf è dichiarato, quindi Derivato :: vf è anche virtuale (indipendentemente dal fatto che sia dichiarato) e sostituisce Base :: vf.

+2

+1 per la citazione del riferimento reale –

10

Quella parola chiave è strettamente facoltativa e non fa alcuna differenza.

+11

Non fa alcuna differenza per il compilatore. Al lettore umano può infatti migliorare la leggibilità. Io dichiaro sempre esplicitamente il virtuale a tutti i livelli di ereditarietà. –

7

La proprietà virtual viene ereditata dalla classe base e si presume che sia presente anche se non la si digita.

1

Il compilatore sa già dalla parola chiave "virtuale" nella classe base che toString è un metodo virtuale. Non c'è bisogno di ripeterlo.

+4

Si potrebbe aggiungere che potrebbe fare la differenza per il lettore umano. – sbi

1

Una funzione una volta virtuale sempre virtuale.

Quindi, in ogni caso, se la parola chiave virtuale non viene utilizzata nelle classi successive, non impedisce che la funzione/metodo sia "virtuale" e che sia sovrascritta. Così il seguente orientamento potrebbe aiutare da un punto di vista del team di sviluppo: -

  • Se la/metodo della funzione dovrebbe essere sovrascritti, utilizzare sempre la parola 'virtuale'. Si tratta in particolare di true quando utilizzato nelle classi interfaccia di base.
  • Se la classe derivata dovrebbe essere sub-classificati ulteriormente esplicitamente stato la parola 'virtuale' per ogni funzione/metodo che può essere ignorata.
  • Se la funzione/metodo nella derivata classe non dovrebbe essere sub-classificato ancora una volta, quindi la parola 'virtuale' è quello di essere commentato indicare che la funzione/metodo di è stato ignorato, ma non ci sono ulteriori classi che lo sostituiscono di nuovo . Questo corso naturalmente non impedisce a qualcuno di ignorare la classe derivata a meno che la classe non venga resa definitiva (non derivabile), ma indica che il metodo non deve essere sostituito da . Es: /*virtual*/ void someFunc();
+0

Per il caso di "essere sovrascritto sempre", si potrebbe voler aggiungere anche lo specificatore puro. – Myke

+0

Penso che ci sia una virgola tra "override" e "always". ad esempio "usa sempre la parola chiave' virtuale' "e non" sempre sovrascritta ". –

+0

@ Ben: hai ragione, Thnx. – Abhay

0

Non importa alla compilatore se non si forniscono il virtuale parola chiave sulle versioni derivate della funzione.

Tuttavia, è una buona idea fornirlo comunque, in modo che chiunque guardi il tuo codice sarà in grado di dire che è una funzione virtuale.

0

È una questione di stile e il programmatore di utenti sa cosa sta succedendo. In C++ 0x puoi usare [[override]] per renderlo più esplicito e visibile. Puoi usare [[base_check]] per forzare l'uso di [[override]].

Se non vuoi o non puoi farlo, usa semplicemente la parola chiave virtuale.

Se si ottiene senza toString virtuale e si esegue il cast di un'istanza di Derive su Base, la chiamata aString() chiamerebbe in realtà Base toString(), poiché per quanto ne sa è un'istanza di Base.