No se puede utilizar un puntero a una función miembro pública proveniente de una base privada.
Considere este código:
class Base {
public:
int foo(int x) const { return 2*x; }
};
class Derived : Base {
public:
using Base::foo;
};
Ahora, Derived
tiene un método foo
público y se puede llamar:
Derived d;
d.foo(2); // compila (como debería)
Sin embargo, no puedo hacer nada si uso el método a través de un puntero:
Derived d;
(d.*&Derived::foo)(2); // no compila porque `Derived::foo` espera un puntero a `Base` y `Derived` no puede ser convertido a su clase base privada (sin una conversión de estilo C).
¿Existe alguna explicación lógica para este comportamiento o quizás es un descuido en el estándar?
davy.ai
El comportamiento descrito no es una omisión en el estándar, sino más bien una consecuencia de las reglas de control de acceso en C++.
Cuando
Derived
hereda deBase
utilizando la palabra clavepublic
, los miembrospublic
deBase
se convierten en miembrospublic
deDerived
, y los miembrosprotected
yprivate
deBase
se convierten en miembrosprotected
deDerived
.Sin embargo, esto solo se aplica a la búsqueda de nombres al acceder a los miembros de
Derived
desde el ámbito de la definición de la claseDerived
o sus funciones miembro. Al acceder a los miembros deDerived
desde fuera de la definición de la clase (como a través de un puntero aDerived
), las reglas de control de acceso de la claseBase
siguen aplicándose.En este caso,
Derived
ha heredado una función miembropublic
llamadafoo
deBase
, pero al intentar llamar a esa función en un objeto de tipoDerived
a través de un puntero, se trata como si fuera un miembro deBase
. Dado queBase
es una clase baseprivate
deDerived
, la llamada no está permitida.Este comportamiento es intencional y coherente con las reglas de control de acceso en C++, que tienen como objetivo hacer cumplir la encapsulación y evitar el acceso no autorizado a los miembros
private
de una clase.