2011-09-05 10 views
8

El siguiente ejemplo sencillo producirá un error de compilación, ya que accidentalmente utilizar la herencia privada:puntero a la clase base y la herencia privada

main.cpp: 21: error: 'A' es una base inaccesible de 'B '

class A 
{ 


}; 

class B : /*ups forgot that -> public*/ A 
{ 


}; 

int main(int , char *[]) 
{ 
    A* test = new B; 

    return 0; 
} 

¿me podría ayudar a explicar por qué es exactamente y es inaccesible en la clase base y por qué se necesita en la conversión B*-A*?

+1

[¿Cuáles son especificadores de acceso? ¿Debo heredar con privado, protegido o público?] (Http://stackoverflow.com/questions/5447498/what-are-access-specifiers-should-i-inherit-with-private-protected-or-public/%5d) es una buena lectura para ti. –

+1

también este enlace puede ser útil http://www.gotw.ca/publications/mill06.htm –

Respuesta

10

herencia privada significa que para todos excepto B (y amigos de B), B no se deriva de A.

+0

¿Podría explicar eso en términos de 'constructores' en el nivel de función? ¿Qué funciones son inaccesibles debido a la herencia privada? –

+0

@Ronald: toda la clase es inaccesible, incluidos todos los constructores y cualquier otro miembro. Nada es accesible. –

+0

¿Pero por qué puedo crear una 'clase B' si la' clase A 'es totalmente inaccesible? Lo siento, estoy confundido :-) –

0

Puesto que B se hereda de A, el constructor por defecto de A sería llamado antes de que el constructor del B. Pero debido a que es privado y no heredado a B, obtienes un error de compilación.

1

El conversiónB*-A* es inaccesible, debido el subobjeto de la clase base es privado. Cuando convierte B* en A*, devuelve el puntero al subobjeto de clase base. Este último debe estar accesible para que la conversión sea accesible. En cualquier función que sea amiga de B, se puede acceder a la conversión. Por cierto, siempre puedes acceder a la conversión mediante un lanzamiento explícito.

A* p = (A*)(new B); 

Tenga en cuenta que en algunos casos sólo se requiere la conversión accesible, pero en algunos casos se requiere que sea un A (más fuerte que accesible) de base pública de B. Por ejemplo, cuando intenta capturar una excepción de tipo B con catch(A&) - se requiere que A ser una clase base pública de B.

+0

El reparto explícito que mencionaste, ¿es funcionalmente el mismo que un 'reinterpret_cast'? Es decir, desde el punto de vista del compilador, ¿convierte dos tipos totalmente independientes? –

+0

@Ronald: Para ser honestos, no estoy seguro. En el estándar, los ejemplos usan molde de estilo C sin mencionar qué molde es. Puedes intentar escribiendo static_cast. Si funciona, entonces es static_cast, de lo contrario es reinterpret_cast –

+0

Armen, gracias por su ayuda. –

7

Could you help me and explain what exactly is inaccessible in the base class and why it is needed in the conversion from B* to A*?

Ouside de B y los amigos de B, el simple hecho de que es un BA no es visible. Esto no oculta una variable miembro o función miembro, sino que oculta la relación misma. Es por ello que a partir main No puede asignar el resultado de new B con un puntero a A, porque en lo que se refiere main, B no es una A (de la misma manera que no se podía hacer A * p = new unrelated;)

cuanto a por qué es necesario, la respuesta es exactamente la misma: porque sin acceso a la relación, el compilador no sabe (bueno, sabe, pero no le dirá) cómo obtener un puntero al sujeto A dentro de B, porque hasta ahora como puede ver dentro de ese contexto, no existe relación entre A y B.

+0

Gracias David, muy buena explicación. Creo que lo tengo ahora :-) –

0

Desde el referencia o puntero de la clase base no puede apuntar al objeto de clase heredada, ¿quiere decir que protegidos y la herencia privada es nada que ver con el polimorfismo?

0

La herencia pública/privada es equivalente a miembro público/privado variable. El resultado de la conversión es una referencia al subobjeto de clase base del objeto de clase derivado.

Creo que la accesibilidad significa la accesibilidad del subobjeto de clase base del objeto de clase derivado. Para el cliente, solo si tenemos herencia pública, se puede acceder al subobjeto de clase base. Para la función miembro de la clase derivada, no importa use public/protected/privaye inheritance, el subobjeto de clase base es accesible.

class A{ 

}; 

class B: private A{ 
private: 
    int* m_pb; 
public: 
    B(){m_pb=new int(10)}; 
    void func() 
    { 
     A* pa= new B;  //OK 
     int *pmb = m_pb; //OK 
    } 

}; 
int main() 
{ 
    B* pb = new B; 
    A* pa= pb;    // inaccessible 
    int *pmb = pb->m_pb; // inaccessible 
} 

OK.I significa que la herencia pública/privada es equivalente a la variable de miembro público/privado.

referencia: http://pic.dhe.ibm.com/infocenter/ratdevz/v8r5/index.jsp?topic=%2Fcom.ibm.tpf.toolkit.compilers.doc%2Fref%2Flangref_os390%2Fcbclr21011.htm

Cuestiones relacionadas