Pregunta

Yo estaba tratando de averiguar lo que sucede cuando una clase derivada declara una función virtual como privado. El siguiente es el programa que escribí

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void func() {
        cout<<"A::func called"<<endl;
    }
    private:
};
class B:public A
{
    public:
    B()
    {
        cout<<"B constructor called"<<endl;
    }
    private:
    void func() {
        cout<<"B::func called"<<endl;
    }
};
int main()
{
    A *a = new B();
    a->func();
    return 0;
}

Sorprendentemente (para mí) la salida fue:

B constructor called
B::func called

No es este violar el acceso privado fijado para esa función. Es este el comportamiento esperado? ¿Es esto es una solución estándar o laguna? Se omiten los niveles de acceso cuando la función de la resolución de las llamadas a través de la VTABLE?

Cualquier idea para este comportamiento sería de gran ayuda.

Además se mencionó que un anulando de forma privada en un miembro virtual impediría nuevas clases de heredarlo. Incluso esto está teniendo problemas. Modificar el programa anterior para incluir:

class C: public B
{
    public:
    void func() {
        cout<<"C::func called"<<endl;
    }
};

y el principal programa de prueba para:

int main()
{
    A *a = new C();
    a->func();
    return 0;
}

salida es:

C::func called
¿Fue útil?

Solución

El comportamiento es correcto. Cada vez que se declara su función como "virtual", se indica al compilador para generar una llamada virtual, en lugar de la llamada directa a esta función. Cada vez que reemplace la función virtual en la clase descendiente, se especifica el comportamiento de esta función (no se cambia el modo de acceso para aquellos clientes, que confían en la interfaz del "padre").

Cambiar el modo de acceso para la función virtual en la clase descendiente significa que desea ocultarlo de los clientes, que utilizan la clase descendiente directa (que dependen de la interfaz "de niños").

Considere el ejemplo:

void process(const A* object) {
   object->func();
}

Función de "proceso" se basa en la interfaz de los padres. Se espera que el trabajo para cualquier clase, el sector público y derivado de A. No se puede B-pública se derivan de una (diciendo "cada B es A"), pero ocultar una parte de su interfaz. Aquellos, que esperan "A" debe recibir una "A" completamente funcional.

Otros consejos

Este es un comportamiento bien definido. Si a eran una B* esto no compila. La razón es que el acceso miembro se ha resuelto de forma estática por el compilador, no de forma dinámica en tiempo de ejecución. Muchos libros de C ++ sugieren que evite la codificación como esto porque confunde codificadores con menos experiencia.

Bueno, que está llamando A::func() que es public aunque en un objeto B que queda anulado por B::func(). Este es un patrón común en las siguientes implicaciones:

  • func no está destinada a ser llamada en objetos derivados <=>

  • <=> no puede ser anulado en clases derivadas de <=>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top