2009-11-05 14 views
9

Si tengo en C++:C++ Implementación de funciones virtuales?

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

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

Entonces si quito virtual de la definición myfunction en class B, ¿significa que si tuviera un class C basado en class B, que no podía anular el myfunction ya que sería compilado estáticamente?

Además, estoy confundido en cuanto a lo que sucede cuando se cambia entre público y privado aquí. Si cambio la definición de myfunction en class B para que sea pública (y la de class A permanece en privado), ¿es esto algún tipo de error grave que no debo hacer? Creo que las funciones virtuales necesitan mantener el mismo tipo, eso es ilegal, pero por favor, avísennos si eso está mal.

Gracias!

+5

no es necesario escribir explícitamente palabra clave "virtual" para los métodos de clase derivados. puedes omitirlo, pero es un buen estilo tenerlo. – varnie

Respuesta

15

La primera definición con 'virtual' es la que importa. Esa función desde la base es de ahí en adelante virtual cuando se deriva de, lo que significa que no necesita 'virtual' para las llamadas de funciones virtuales reimplementadas. Si una firma de función en una clase base no es virtual, sino virtual en las clases derivadas, entonces la clase base no tiene comportamiento polimórfico.

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

¡Gracias, eso fue muy útil! – ash

+0

De nada. También debería agregar que "Base * b" es en realidad un Derived1. Use dynamic_cast para realizar downcasting seguro en situaciones que lo necesite. –

+0

Pero el ejemplo de los autores cubre a los miembros privados. – bua

1

si se quita virtual de la definición myfunction en la clase B,

compilador añadirá esto para usted. Para completar V-Table para tipos polimórficos.

!! PERO !!

Sólo tendrá acceso a miembros públicos de la clase A (clase B: public A)

la definición:

class B: private A 
{ 

} 

causará que todos los miembros (incluso festivos) de la clase A, lo hará volverse privado para la clase B. Simplifica No tendrá acceso a los miembros públicos.

Para solucionar Puede declarar algún amigo:

class A 
{ 
    private: 
     friend class B; 
} 

Más gran información HERE.

+0

¡Gracias por la rápida respuesta! – ash

+0

La respuesta es un poco confusa para mí. De la respuesta leí que la clase B no puede acceder a los miembros públicos que hereda de la clase A, que luego se resuelve declarando a B amigo de A. No creo que eso sea lo correcto. B puede acceder a los miembros públicos y protegidos desde A, pero los usuarios de B no pueden acceder a los miembros públicos de A, y esto no se resolverá con la declaración de amigo. ¿Estoy malinterpretando algo? – stefaanv

+0

Sí, te has perdido la herencia privada de mi ejemplo. – bua

7

una vez que una función se hace virtual en una clase base, será virtual para cualquier otra subclase.

público, protegido y privado no afectan la naturaleza virtual de las funciones.

+0

¡Gracias! Gracias por la información de visibilidad. – ash

+0

Al hacer que sus funciones virtuales estén protegidas o sean privadas, puede indicarles a los usuarios de su clase si deben llamarlos en la subclase o no. http://www.gotw.ca/publications/mill18.htm –

0

El comportamiento de virtual es que afecta a qué método se llama cuando se tiene un puntero de un tipo que apunta a un objeto de un subtipo. Por ejemplo:

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

Lo que ocurre cuando se llama a obj->myfunction() depende de si A declara myfunction a ser virtual. Si no es virtual, el razonamiento es: tenemos un puntero de tipo A, por lo que llamamos a la función definida en A, y el resultado es 1.Si A define myfunction como virtual, sin embargo, se realiza una búsqueda en tiempo de ejecución en función del tipo del objeto real, en lugar del tipo del puntero; dado que el objeto es realmente un B, se utiliza la implementación definida en B y el resultado es 2.

Se puede encontrar más información en the C++ FAQ Lite section on virtual functions.

Cuestiones relacionadas