2011-04-12 10 views
13

tengo el siguiente ejemplo de código que no se compila:herencia privada: nombre del error de búsqueda

#include <stdio.h> 

namespace my 
{ 
    class base1 
    { // line 6 
    }; 

    class base2: private base1 
    { 
    }; 

    class derived: private base2 
    { 
    public: 
     // The following function just wants to print a pointer, nothing else! 
     void print(base1* pointer) {printf("%p\n", pointer);} 
    }; 
} 

El error que las impresiones GCC es:

test.cpp:6: error: `class my::base1' is inaccessible

test.cpp:17: error: within this context

Ahora, puedo adivinar cuál es el problema es: al mirar la declaración de print, el compilador ve base1 y piensa: base1 es el subobjeto de clase base de derived* this, ¡pero no tiene acceso a él! Aunque pretendo que base1 sea solo un nombre de tipo.

¿Cómo puedo ver en el estándar de C++ que este es un comportamiento correcto y no un error en el compilador (estoy seguro de que no es un error, todos los compiladores que revisé se comportaron de esa manera)?

¿Cómo puedo reparar este error? Todas las siguientes correcciones funcionan, pero ¿cuál debo elegir?

void print(class base1* pointer) {}

void print(::my:: base1* pointer) {}

class base1; void print(base1* pointer) {}


Editar:

int main() 
{ 
    my::base1 object1; 
    my::derived object3; 
    object3.print(&object1); 
} 
+0

Se puede publicar el main()? –

+0

¡Buen ejemplo que muestra que la herencia privada no es lo mismo que la composición! – curiousguy

Respuesta

12

La sección que está buscando es 11,1. Se sugiere el uso de mi :: :: Base1 * para evitar este:

[ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. — end note ]

[ Example: 
class A { }; 
class B : private A { }; 
class C : public B { 
A *p; 
// error: injected-class-name A is inaccessible 
:: A * q ; 
// OK 
}; 
+0

¿podría explicar qué es inyectado-nombre-clase? – davka

+1

Capítulo 9, punto 2: Un nombre de clase se inserta en el ámbito en el que se declara inmediatamente después de que se vea el nombre de clase. El nombre de clase también se inserta en el alcance de la clase en sí; esto se conoce como el nombre de clase inyectado. A los efectos de la verificación de acceso, el nombre de la clase inyectada se trata como si fuera un nombre de miembro público. Un especificador de clase se conoce comúnmente como una definición de clase. Una clase se considera definida después de que se haya visto la llave de cierre de su especificador de clase aunque sus funciones miembro en general aún no están definidas. –

+1

Si está satisfecho con la respuesta proporcionada, @anatolyg, ¿podría marcar esto como aceptado para que otros también puedan verlo? –

Cuestiones relacionadas