Al hacer que la herencia sea privada, básicamente estás diciendo que incluso el hecho de que B herede de A (en absoluto) es privado, no accesible / visible para el mundo exterior.
Sin entrar en una larga discusión sobre lo que sucedería si estuviera permitido, el simple hecho es que no está permitido. Si desea usar un puntero a la base para referirse a un objeto de tipo derivado, entonces está bastante atrapado con el uso de herencia pública.
La herencia privada no necesariamente (ni siquiera normalmente) pretende seguir el principio de sustitución de Liskov . La herencia pública afirma que un objeto derivado se puede sustituir por un objeto de la clase base, y la semántica adecuada seguirá resultando. Sin embargo, la herencia privada no lo afirma. La descripción habitual de la relación implícita en la herencia privada es "se implementa en términos de".
La herencia pública significa que una clase derivada mantiene todas las capacidades de la clase base y potencialmente agrega más. La herencia privada a menudo significa más o menos lo contrario: que la clase derivada usa una clase base general para implementar algo con una interfaz más restringida.
Por ejemplo, supongamos por el momento que los contenedores de la biblioteca estándar de C ++ se implementaron usando herencia en lugar de plantillas. En el sistema actual, std::deque
y std::vector
son contenedores, y std::stack
es un adaptador de contenedor que proporciona una interfaz más restringida. Dado que se basa en plantillas, puede utilizarlo std::stack
como adaptador para std::deque
o std::vector
.
Si quisiéramos proporcionar esencialmente lo mismo con la herencia, probablemente usaríamos herencia privada, por std::stack
lo que sería algo como:
class stack : private vector {
};
En este caso, definitivamente no queremos que el usuario pueda manipular nuestro stack
como si fuera un vector
. Hacerlo podría (y probablemente lo haría) violar las expectativas de una pila (por ejemplo, el usuario podría insertar / eliminar elementos en el medio, en lugar de una forma puramente similar a una pila como se pretendía). Básicamente, lo estamos usando vector
como una forma conveniente de implementar nuestra pila, pero si (por ejemplo) cambiamos la implementación para que sea stack
independiente (sin dependencia de una clase base) o la reimplementamos en términos de std::deque
, no queremos eso para afectar cualquier código de cliente: para el código de cliente, se supone que esto es solo una pila, no una variedad especializada de vector (o deque).
protected
Lo hace. Y si
A* p = new B;
se permitieron, entonces se
B
podría acceder a los miembros heredados de cualquiera desde el mundo exterior, simplemente haciendo unA*
. Dado que se heredan de forma privada, ese acceso es ilegal, y también lo es el upcast.fuente
clang++
da un mensaje de error un poco más comprensible:example.cpp:9:13: error: cannot cast 'B' to its private base class 'A' A* ab = new B; ^ example.cpp:6:11: note: declared private here class B : private A { }; ^~~~~~~~~ 1 error generated.
No soy un experto en C ++, pero parece que simplemente no está permitido. Iré a hurgar en la especificación y veré qué se me ocurre.
Editar: aquí está la referencia relevante de la especificación - Sección 4.10 Conversiones de puntero , párrafo 3:
fuente
Es bastante simple: el hecho de que
A
se herede de forma privada significa que el hecho de que seB
extiendeA
es un secreto, y solo loB
"conoce". Esa es la definición misma de herencia privada.fuente
private
conprotected
.B
subclases (y amigos) deB
. "A* ab = new B;
" sería legal en una clase hipotéticaC
que fuera una subclase deB
.La herencia privada significa que fuera de la clase derivada, la información de herencia está oculta. Eso significa que no puede convertir la clase derivada a la clase base: la persona que llama no conoce la relación.
fuente
private
El único negocio debería ser controlar cómo se comportan los miembros. ¿Cuál sería el daño si la información de la herencia no se oculta?Esto esta funcionando
#include <iostream> using namespace std; class A{ public: virtual void update() = 0; }; class B: public A{ public: virtual void update(){std::cout<<"hello";}; }; int main() { A *a = new B(); a->update(); return 0; }
fuente