2010-09-30 21 views
6

Dato il seguente frammento,C++ virtuale Const Funzione

class Base 
{ 
public: 
    virtual void eval() const 
    { 
     std::cout<<"Base Const Eval\n"; 
    } 
}; 

class Derived:public Base 
{ 
public: 
    void eval() 
    { 
     std::cout<<"Derived Non-Const Eval\n"; 
    } 
}; 

int main() 
{ 

    Derived d; 
    Base* pB=&d; 

    pB->eval(); //This will call the Base eval() 

    return 0; 
} 

Perché il PB> eval() chiamerà la Base :: eval()?

si

risposta

6

Grazie Questo perché si è dichiarato const e l'altro non è. Una funzione è nascosta dall'altra. La funzione in Derivata nasconde quella in Base perché hanno lo stesso nome mentre non hanno la stessa funzione.

Il mio compilatore dà un avvertimento qui, il tuo?

+0

Curioso: Cosa compilatore? Quale opzione di avviso? – Arun

+0

Se si attiva l'avviso sulla maggior parte dei compilatori lo farà. –

8

Nella classe Derived, il prototipo di eval non corrisponde a quello della funzione virtuale in Base. Quindi non sovrascriverà la funzione virtuale.

Base::eval() const; 
Derived::eval(); //No const. 

Se si aggiunge il const per Derived::eval(), si dovrebbe ottenere un comportamento virtuale.

2

Il const è parte della firma della funzione. Per sovrascrivere una funzione, l'override deve avere esattamente la stessa firma della versione base, in questo caso no.

Si consideri che il codice chiamante non ha bisogno di sapere nulla su Derived - sta chiamando una funzione const su un Base. Non ti aspetteresti che quella chiamata finisca in una funzione non const che potrebbe cambiare le cose sulla classe.

5

$ 10,3/2- "Se una funzione membro virtual vf è dichiarato in una base di classe e in una classe derivata, derivato direttamente o indirettamente dalla base, una funzione membro vf con lo stesso nome, parametro di tipo-list (8.3.5), cv-qualificazione e refqualifier (o assenza di stesso) come base :: VF è dichiarato, quindi Derived :: VF è anche virtuale (o meno è così dichiarato ) e sostituisce Base :: vf. "

111) Una funzione con lo stesso nome ma un diverso elenco di parametri (Clausola 13) come una funzione virtuale non è necessariamente virtuale e non fa override. L'uso dello specificatore virtuale nella dichiarazione di una funzione di override è legale ma è ridondante ridondante (ha semantica vuota). Il controllo accessi (clausola 11) non è considerato nel determinare l'override.

Come nota a parte, non parla delle specifiche di accesso. Pertanto, gli specificatori di accesso classe base e classe derivata per la funzione ignorata potrebbero essere diversi

Ciò significa che Derived :: eval non sovrascrive Base :: eval in quanto le loro qualifiche cv differiscono.

8

È possibile tradurre nella vostra mente:

virtual void Base::eval() const; 
void Derived::eval() ; 

a

void eval(const Base *this, size_t vtable_offset); 
void eval(Derived *this); 

e vedere mediante ispezione quanto poco il secondo corrisponde la firma del primo.

+0

+1: buon modello mentale. (Potresti voler contrassegnare il tuo codice.) – Arun

2

In C++ 0x, la situazione è rilevabile in fase di compilazione utilizzando le parole chiave base_check e override. Excerpt from wikipedia:

L'attributo [[base_check]] su un classe/struttura significa che qualsiasi implicita imperativa darà luogo ad un errore di compilatore. Qualsiasi override deve essere esplicitamente contrassegnato con l'attributo [[override]].

Molto probabilmente (non molto sicuro circa la sintassi):

class Derived [[base_check]] : public Base { 

    virtual void eval [[override]]() { 
     .... 
    } 
}; 
Problemi correlati