2011-08-26 17 views
16

Tengo un problema similar al descrito en el siguiente enlace donde una clase base heredada de forma privada da un error de "inaccesible dentro de este contexto" cuando intento declarar un miembro de la clase base dentro de la clase derivada: http://bytes.com/topic/c/answers/164246-private-inheritance-renders-class-inaccessibleLa herencia privada oculta la clase base con el error "inaccesible dentro de este contexto"

explícitamente referencia X con X :: funciona en el caso anterior, pero lo que si el código está en una función como:

void fooby() 
{ 
    class X {}; 

    class Y : private X {}; 

    class Z : public Y 
    { 
    public: 
     X x; // compiler "inaccessible within this context" error 
    }; 
}; 

Cómo ¿Hace referencia a X en este caso?

Si fooby fuera una estructura/clase, entonces :: fooby :: X funcionaría, pero no estoy seguro de cómo hacerlo en el caso anterior.

+0

¿Qué intenta hacer teniendo tanto un miembro como una clase base del mismo tipo? Quizás eso ayude con una sugerencia alternativa. –

+0

@Mark B: esto es solo un simple ejemplo artificial para ilustrar el comportamiento que estoy tratando de comprender –

Respuesta

10

El problema que se enfrentan es que hay un identificador inyectado X en Y (y todos los tipos derivados) que se refiere a X, que no es accesible por debajo de Y.

en el caso común de tipos definidos por el usuario que se declaró a nivel de espacio de nombres, se puede utilizar el espacio de nombres para calificar el tipo y tener acceso:

class X {}; 
class Y : X {}; 
class Z : Y { 
    ::X x;   // or Namespace::X 
}; 

Porque te ar e definir sus tipos dentro de una función que no es una opción válida.

Como alternativa, puede solucionar el problema con otras soluciones. Como @Eugene propone, puede crear un identificador alternativo para referirse a X:

typedef class X {} another_name; 
class Y : X {}; 
class Z : Y { 
    another_name x; 
}; 

O puede añadir un typedef dentro Y para proporcionar el tipo de los tipos derivados:

class X {}; 
class Y : X { 
public: 
    typedef X X; 
}; 
class Z : Y { 
    X x; 
}; 

Esta última opción funciona porque agregará un identificador X dentro de Y que es public y se refiere al tipo, por lo que el compilador encontrará el tipo allí y lo usará en Z.

+0

+1 gran respuesta y aprendí sobre el uso de 'clase' de una manera diferente hoy. –

+0

Su "siguiente opción" ("clase X x;") es incorrecta. Eso no funcionará, es lo mismo y se refiere al nombre de la clase inyectada privada heredada y, por lo tanto, inaccesible. Parece que piensas erróneamente que el nombre de clase inyectado es un objeto en lugar de un tipo. El nombre de clase inyectado se refiere a una clase y es un nombre de tipo. –

+0

@Johannes: Sí, tienes razón en que tuve esa idea equivocada. De hecho, estaba tratando de buscar esto en el estándar (g ++ lo acepta 4.2/4.7, pero clang ++ y comeau lo rechazan). Parece que tanto la 'clase X x;' como la 'identidad :: type' fallan. –

9

Buena pregunta, no puedo encontrar la manera de hacerlo. La única opción que veo es introducir typedef fuera de Z:

typedef X PITA; 
class Z : public Y 
{ 
public: 
    PITA x; // ok 
}; 
Cuestiones relacionadas