2009-11-05 20 views
9

Se ho in C++:C++ Implementazione della funzione virtuale?

class A { 
    private: virtual int myfunction(void) {return 1;} 
} 

class B: public A { 
    private: virtual int myfunction(void) {return 2;} 
} 

Poi se tolgo virtual dalla definizione myfunction in class B, vuol dire che se avessi avuto un class C basata su class B, che non potevo ignorare il myfunction dal momento che verrebbe compilato staticamente?

Inoltre, sono confuso su cosa succede quando si passa in giro pubblico, e privato qui. Se cambio la definizione di myfunction in class B in pubblica (e quella in class A rimane privata), si tratta di una sorta di grave errore che non dovrei fare? Penso che le funzioni virtuali debbano mantenere lo stesso tipo in modo che sia illegale, ma ti preghiamo di sapere se è sbagliato.

Grazie!

+5

non è necessario scrivere esplicitamente la parola chiave "virtuale" per i metodi della classe derivata. puoi ometterlo, ma è un buon stile averlo. – varnie

risposta

15

La prima definizione con "virtuale" è quella che conta. Quella funzione dalla base è da allora in poi quando viene derivata, il che significa che non è necessario "virtuale" per le chiamate alle funzioni virtuali reimplementate. Se una firma di funzione in una classe base non è virtuale, ma virtuale nelle classi derivate, la classe base non ha un comportamento polimorfico.

class Base 
{ 
    public: 
    void func(void){ printf("foo\n"); } 
}; 
class Derived1 : public Base 
{ 
    public: 
    virtual void func(){ printf("bar\n"); } 
}; 
class Derived2 : public Derived1 
{ 
    public: 
    /* reimplement func(), no need for 'virtual' keyword 
     because Derived1::func is already virtual */ 
    void func(){ printf("baz\n"); } 
}; 

int main() 
{ 
    Base* b = new Derived1; 
    Derived1* d = new Derived2; 

    b->func(); //prints foo - not polymorphic 
    d->func(); //prints baz - polymorphic 
} 
+0

Grazie, è stato molto utile! – ash

+0

Prego. Dovrei anche aggiungere che "Base * b" è in realtà un derivato1. Utilizza dynamic_cast per eseguire downcast in sicurezza nelle situazioni in cui ne hai bisogno. –

+0

Ma l'esempio degli autori riguarda i membri privati. – bua

1

se si rimuove virtual dalla definizione myfunction in classe B,

compilatore aggiungerà questo per voi. Per compilare V-Table per i tipi polimorfici.

!! MA !!

Si avrà accesso solo ai membri pubblici della classe A (Classe B: public A)

la definizione:

class B: private A 
{ 

} 

causerà che tutti i membri (anche pubblici) di classe A, volontà diventare privato per la classe B. Semplifica Non si avrà accesso a A membri pubblici.

Per risolvere È possibile dichiarare qualche amico:

class A 
{ 
    private: 
     friend class B; 
} 

Altri grandi informazioni HERE.

+0

Grazie per la rapida risposta! – ash

+0

La risposta è un po 'confusa per me. Dalla risposta ho letto che la classe B non può accedere ai membri pubblici che eredita dalla classe A, che viene poi risolta dichiarando B amico di A. Non penso che sarebbe giusto. B può accedere ai membri pubblici e protetti da A, ma gli utenti di B non possono accedere ai membri pubblici di A e questo non sarà risolto dalla dichiarazione di amicizia. Mi manca interpretare qualcosa? – stefaanv

+0

Sì, hai perso l'ereditarietà privata dal mio esempio. – bua

7

una volta che una funzione viene resa virtuale in una classe base, sarà virtuale per ogni altra sottoclasse.

pubbliche, protette e private non influiscono sulla natura virtuale delle funzioni.

+0

Grazie! Grazie per le informazioni sulla visibilità. – ash

+0

Rendendo le tue funzioni virtuali protette o private puoi suggerire agli utenti della tua classe se sono obbligati a chiamarle nella sottoclasse o meno. http://www.gotw.ca/publications/mill18.htm –

0

Il comportamento di virtual è che effetti che il metodo viene chiamato quando si dispone di un puntatore di un tipo che punta a un oggetto di un sottotipo. Per esempio:

B* obj = new B; 
A* base = obj; 

Cosa succede quando si chiama obj->myfunction() dipende dal fatto che A dichiara myfunction ad essere virtuale. Se non è virtuale, il ragionamento è: abbiamo un puntatore del tipo A, quindi chiamiamo la funzione definita in A e il risultato è 1.Se A definisce virtuale myfunction, tuttavia, una ricerca viene eseguita in fase di esecuzione in base al tipo dell'oggetto reale, anziché al tipo del puntatore; poiché l'oggetto è in realtà un B, viene utilizzata l'implementazione definita in B e il risultato è 2.

Ulteriori informazioni sono disponibili in the C++ FAQ Lite section on virtual functions.

Problemi correlati