2011-03-20 11 views
5

Me encontré con este problema accidentalmente cuando revisaba la herencia y hacia arriba/abajo de la transmisión. ¿Por qué no está permitido (el código está comentado para mostrar secciones que no están permitidas)? Ahora puedo adivinar por qué no está permitido, pero una respuesta objetiva sería genial.Casting de herencia privada/protegida

En cuanto al código que se animales, sé que es porque (Base *) es una conversión de estilo C, que es esencialmente un reinterpret_cast en C++ que a su vez significa que en este caso lo hará da como resultado un comportamiento indefinido. Por favor, corríjame si estoy equivocado.

class Base 
{ 
}; 

class Derived : public Base 
{ 
}; 

class DerivedProt : protected Base 
{ 
}; 

class DerivedPriv : private Base 
{ 
}; 

int main() 
{ 
    Base* a = new Derived(); 
    Base* b = new DerivedProt(); // Not allowed 
    Base* c = new DerivedPriv(); // Not allowed 

    Base* d = (Base*) new DerivedProt(); // Allowed but undefined behavior...? 
    Base* e = (Base*) new DerivedPriv(); // Allowed but undefined behavior...? 
} 

Respuesta

0

Parece que estás en lo cierto.

Una cosa para recordar es que los principios tradicionales de OO como el LSP solo describen la herencia pública. La herencia no pública se encuentra entre la herencia y la composición, el subobjeto base no es público como la composición, pero también puede aprovechar las características que dependen de la herencia, como las funciones virtuales.

Al igual que un subobjeto compuesto, sin embargo, solo la clase (o sus descendientes, en el caso de herencia protegida) puede obtener la dirección del subobjeto.

6

El estándar especifica que los moldes de estilo C pueden realizar esta conversión. Es el único elenco que C-style arroja puede pero ningún molde de C++ puede hacerlo. Los resultados no son indefinidos por lo que yo sé; simplemente no está permitido por ningún otro elenco.

+1

Incluso si no se trata de un comportamiento indefinido, sigue siendo una idea increíblemente mala y debe evitarse. Una cosa que es muy peligrosa sobre este elenco es que el compilador intentará hacerlo incluso cuando no haya una relación de herencia y ni siquiera genere una advertencia. –

+5

Tuve que verificar con Comeau en línea para ver si mi compilador se equivocó. No, reinterpret_cast <> puede hacer esto también. –

+0

@HansPassant Pero 'reinterpret_cast' no conoce ni se preocupa por las clases base. No se puede usar para moldes hacia arriba o hacia abajo. – curiousguy