2010-09-30 33 views
6

Dado el siguiente fragmento,C++ virtual Const Función

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; 
} 

Por qué la PB-> eval() llamará a la Base :: eval()?

Gracias

Respuesta

6

Esto es porque uno es declarado const y el otro no lo es. Una función está siendo escondida por la otra. La función en Derived está ocultando la de Base porque tienen el mismo nombre mientras que no tienen la misma función.

Mi compilador le da una advertencia aquí, ¿lo tiene el tuyo?

+0

curioso: ¿Qué compilador? ¿Qué opción de advertencia? – Arun

+0

Si activa la advertencia, la mayoría de los compiladores lo harán. –

8

En su clase Derived, el prototipo de eval no coincide con el de la función virtual en Base. Por lo tanto, no anulará la función virtual.

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

Si agrega la const para Derived::eval(), usted debe conseguir un comportamiento virtual.

2

El const es parte de la firma de la función. Para anular una función, la anulación debe tener exactamente la misma firma que la versión base; en este caso, no.

Tenga en cuenta que el código de llamada no necesita saber nada sobre Derived - llama a una función const en Base. No esperarías que la llamada terminara en una función no const que podría cambiar las cosas sobre la clase.

5

$ 10,3/2- "Si una función miembro virtual vf se declara en una base de clase y en una clase derivada, derivados directa o indirectamente de Base, un vf función miembro con el mismo nombre, -tipo de parámetro-list (8.3.5), cv-calificación, y refqualifier (o ausencia de los mismos) como Base :: vf se declarados, entonces Derivado :: vf también es virtual (si es o no es tan declarado) y reemplaza 111 Base :: vf. "

111) Una función con el mismo nombre pero una lista diferente de parámetros (Cláusula 13) como una función virtual no es necesariamente virtual y no lo hace anulación. El uso del especificador virtual en la declaración de una función de anulación es legal pero redundante (tiene semántica vacía). El control de acceso (cláusula 11) no se considera al determinar la anulación.

Como nota aparte, tenga en cuenta que no habla de las especificaciones de acceso. Por lo tanto, la clase base y los especificadores de acceso de clase derivados para la función anulada podrían ser diferentes

Esto significa que Derived :: eval no anula Base :: eval ya que sus calificaciones de cv son diferentes.

8

Usted puede traducir en su mente:

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

a

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

y ver por inspección lo poco que el segundo coincide con la firma de la primera.

+0

+1: Buen modelo mental. (Es posible que desee marcar su código). – Arun

2

En C++ 0x, la situación es detectable en tiempo de compilación utilizando las palabras clave base_check y override. Excerpt from wikipedia:

El atributo [[base_check]] en un clase/struct significa que cualquier implícita primordial dará lugar a un error compilador. Cualquier sobrescritura debe ser marcada explícitamente con el atributo [[anular]].

Lo más probable (no muy seguro acerca de la sintaxis):

class Derived [[base_check]] : public Base { 

    virtual void eval [[override]]() { 
     .... 
    } 
}; 
Cuestiones relacionadas