2012-06-17 15 views
37

supponiamo che questo scenario in Visual C++ 2010:metodi non-virtuali imperative

#include <iostream> 
#include <conio.h> 

using namespace std; 

class Base 
{ 
public: 
    int b; 
    void Display() 
    { 
     cout<<"Base: Non-virtual display."<<endl; 
    }; 
    virtual void vDisplay() 
    { 
     cout<<"Base: Virtual display."<<endl; 
    }; 
}; 

class Derived : public Base 
{ 
public: 
    int d; 
    void Display() 
    { 
     cout<<"Derived: Non-virtual display."<<endl; 
    }; 
    virtual void vDisplay() 
    { 
     cout<<"Derived: Virtual display."<<endl; 
    }; 
}; 

int main() 
{ 
    Base ba; 
    Derived de; 

    ba.Display(); 
    ba.vDisplay(); 
    de.Display(); 
    de.vDisplay(); 

    _getch(); 
    return 0; 
}; 

Teoricamente, l'uscita di questa piccola applicazione dovrebbe essere:

  • Base: visualizzazione non virtuali.
  • Base: display virtuale.
  • Base: display non virtuale.
  • Derivato: display virtuale.

perché il metodo di visualizzazione della classe Base non è un metodo virtuale, pertanto la classe derivata non dovrebbe essere in grado di sovrascriverla. Destra?

Il problema è che quando faccio funzionare l'applicazione, stampa questo:

  • Base: visualizzazione non virtuali.
  • Base: display virtuale.
  • Derivato: display non virtuale.
  • Derivato: display virtuale.

Quindi non ho capito il concetto di metodi virtuali o qualcosa di strano accade in Visual C++.

Qualcuno potrebbe aiutarmi con una spiegazione?

+0

avresti assolutamente __Base: display non virtuale .__ quando cambi la tua linea in 'de.Base :: Display()'. –

risposta

50

Sì, stai fraintendendo un po '.

Il metodo con lo stesso nome sulla classe derivata nasconderà il metodo padre in questo caso. Immagineresti che se così non fosse, provare a creare un metodo con lo stesso nome di un metodo non virtuale di classe base dovrebbe generare un errore. È permesso e non è un problema - e se chiami il metodo direttamente come hai fatto, sarà chiamato bene.

Tuttavia, essendo non virtuali, i meccanismi di ricerca del metodo C++ che consentono il polimorfismo non verranno utilizzati. Ad esempio, se hai creato un'istanza della tua classe derivata ma hai chiamato il tuo metodo "Display" tramite un puntatore alla classe base, verrà chiamato il metodo della base, mentre per "vDisplay" verrà chiamato il metodo derivato.

Ad esempio, provare aggiungendo queste righe:

Base *b = &ba; 
b->Display(); 
b->vDisplay(); 
b = &de; 
b->Display(); 
b->vDisplay(); 

... e osservare l'output come previsto:

Base: visualizzazione non virtuali.
Base: display virtuale.
Base: display non virtuale.
Derivato: display virtuale.

+0

Ciao @ sje397, grazie per la risposta. Puoi scrivere un esempio di chiamata al metodo, come hai detto, tramite un puntatore alla classe base? Grazie! –

+0

@Leif Lazar: fatto. – sje397

+0

anche come ho detto puoi anche chiamare il metodo di base (non virtuale) dall'istanza derivata, usando la sintassi della risoluzione dell'ambito. –

3

Sì avete capito male un po ':

Pure funzioni virtuali:

virtual void fun1()=0 -> deve essere sottoposto a override in classe derivata

funzioni virtuali:

virtual void fun2() -> può essere ignorato

funzioni normali:

void fun3() -> non hanno la precedenza è

Al fine di raggiungere il polimorfismo runtime è necessario eseguire l'override funzioni virtuali in C++

0

Penso che potrebbe essere anche meglio guardare nel contesto del binding statico vs dinamico.

Se il metodo è non virtuale (è già di default in C++ a differenza di Java), il metodo si lega al suo chiamante al momento della compilazione che è impossibile conoscere l'oggetto reale che sarà puntato in fase di esecuzione. Quindi, il tipo variabile è tutto ciò che conta e che è la "Base".

Problemi correlati