c++ - ¿Por qué la conversión entre derivado*a base*falla con herencia privada?
private derived (7)
$ 11.2 / 4 estados-
Una clase base B de N es accesible en R, si
- un miembro público inventado de B sería un miembro público de N, o
- R ocurre en un miembro o amigo de la clase N, y un miembro público inventado de B sería un miembro privado o protegido de N, o
- R ocurre en un miembro o amigo de una clase P derivada de N, y un miembro público inventado de B sería un miembro privado o protegido de P, o
- existe una clase S tal que B es una clase base de S accesible en R y S es una clase base de N accesible en R. "
Aquí ''B'' es ''Base'', ''N'' es ''Derivado'' y ''R'' es principal.
Considere la segunda viñeta: "R aparece en un miembro o amigo de una clase N, ...". Esta cláusula no se aplica ya que ''R'' (principal) no es miembro ni amigo de ''N'' (Derivado)
Considere la tercera viñeta: ''R aparece en un miembro o amigo de una clase P ...''. Este claus tampoco se aplica por las mismas razones que arriba.
Considere la cuarta viñeta: una vez más, esta cláusula no se aplica
Por lo tanto, podemos concluir que ''Base'' no es una clase accesible de ''Derivado''.
$ 11.2 / 5 estados -
Si una clase base es accesible, uno puede convertir implícitamente un puntero a una clase derivada a un puntero a esa clase base (4.10, 4.11). [Nota: se deduce que los miembros y amigos de una clase X pueden convertir implícitamente una X * en un puntero a una clase base inmediata o privada protegida de X. — nota final]
Dado que la Base
no es una clase accesible de Derived
cuando se accede en la página main
, la conversión Estándar de la clase Derivada a la clase Base está mal formada. De ahí el error.
EDIT 2:
Estudie los mensajes de error de algunos compiladores populares y eso debería ayudarlo a comprender mejor. Observe cómo la palabra "inaccesible" aparece con tanta frecuencia y de manera constante en todos los mensajes de error
Las referencias son del proyecto de norma N3000. Todavía tengo que descargar el último borrador :)
GCC prog.cpp: en la función ''int main ()'': prog.cpp: 27: error: ''base'' es una base inaccesible de ''derivada''
Comeau Online "ComeauTest.c", línea 26: error: no se permite la conversión a una clase base inaccesible "base" ptr = nuevo derivado;
Error VS2010 C2243: ''tipo conversión'': la conversión de ''derivado *'' a ''base *'' existe, pero es inaccesible
Aquí está mi código -
#include<iostream>
using namespace std;
class base
{
public:
void sid()
{
}
};
class derived : private base
{
public:
void sid()
{
}
};
int main()
{
base * ptr;
ptr = new derived; // error: ''base'' is an inaccessible base of ''derived''
ptr->sid();
return 0;
}
Esto da un error de tiempo de compilación.
error: ''base'' is an inaccessible base of ''derived''
Dado que el compilador intentará llamar a la clase base sid()
¿por qué recibo este error? Puede alguien por favor explicar esto.
Chusbad proporcionó una explicación detallada sobre el estándar, intentaré proporcionar una explicación accesible.
En C ++, hay 3 especificadores de nivel de acceso: public
, protected
y private
. Estos están destinados a determinar que la OMS puede acceder a métodos, atributos o clases básicas. Es típico entre los lenguajes orientados a objetos.
Aquí, elegiste private
herencia private
. Conceptualmente, esto significa que usted busca OCULTAR el hecho de que Derived
hereda de la Base
a personas externas, lo que generalmente significa que esto es un detalle de la implementación.
Como consecuencia, el "exterior" desconoce esta relación. Esto es aplicado por el compilador con este mensaje inaccessible
.
Desde el punto de vista del diseño, private
herencia private
no es generalmente requerida. El principio de sustitución de Liskov se aplica y usted utiliza public
herencia public
, o bien es un detalle de implementación y utiliza la composición.
Debe declarar su función sid () en la clase base como virtual. Una función virtual puede ser reemplazada por una clase derivada. De lo contrario, es probable que obtenga un error del compilador.
Prueba esto:
#include<iostream>
#include<conio.h>
using namespace std;
class base
{
private:
public:
virtual void sid() // You might want to declare sid virtual
{
cout<<"base";
}
virtual ~base() // You then probably need a virtual destructor as well.
{
}
};
class derived : public base //public inheritance
{
private:
public:
void sid()
{
cout<<"derived";
}
};
int main()
{
base * ptr;
ptr = new derived;
ptr->sid();
getch();
return 0;
}
Sospecho que el problema es que no se puede convertir un puntero derivado en un puntero base, ya que la herencia es privada.
Usted sabe que la class derived
hereda de class base
, pero la función main()
no lo sabe. La razón por la que la función main()
no lo sabe es que usted hizo que la class derived
hereda de forma PRIVADA de class base
.
Por lo tanto, cuando intenta asignar new derived
a ptr
, los tipos de puntero no son compatibles.
esto da el error C2243: ''type cast'': existe la conversión de ''derivado *'' a ''base *'', pero es inaccesible Esta clase derivada se ha heredado de forma privada .por lo tanto, el objeto de clase base no se crea cuando se obtiene la creación. Para crear el objeto derivado, las primeras llamadas van para crear el objeto de clase base que no sucede. La solución es derivar la clase públicamente. no importa si usa palabras clave virtuales con funciones miembro o no.