tipos simple resueltos relaciones programacion orientada objetos herencia entre ejercicios ejemplos clases c++ inheritance visual-studio-2013

c++ - simple - tipos de herencia en java



Error con la herencia de clase anidada (5)

Cita de cppreference :

Un nombre que es privado de acuerdo con la búsqueda de nombre no calificado, puede ser accesible a través de la búsqueda de nombre calificado

Con esto en mente, veamos cómo funcionaría la búsqueda de nombres no calificados para el primer ejemplo:

class A {}; class B : private A {}; class C : private B { public: class D : private A {}; // Error here };

  1. A se busca dentro del alcance de C Si se hubiera definido allí, no habría ningún problema.
  2. Se da cuenta de que A es heredado de forma privada por su clase B (privada) de base y, por lo tanto, arroja un error de compilación. Clang dice:

    note: constrained by private inheritance here: class B : private A {};

De nuevo, según la cita, debería funcionar, si usa un nombre completamente calificado, como lo ha demostrado

class D : private ::A {};

Y en cuanto a tu último ejemplo:

class A {}; class C : private A { public: class D : private A {}; };

Funciona porque la búsqueda de nombre funciona para todos los nombres que forman parte de la misma clase. Para citar de cppreference nuevamente:

Todos los miembros de una clase (cuerpos de funciones miembro, inicializadores de objetos miembros y todas las definiciones de clase anidadas) tienen acceso a todos los nombres a los que puede acceder una clase.

class A {}; class B : private A {}; class C : private B { public: class D : private A {}; // Error here };

Este código proporciona el siguiente error (en VS 2013):

nested.cpp (8): error C2247: ''A'' no accesible porque ''B'' usa ''privado'' para heredar de ''A''

Se soluciona si cambio la definición de D así:

class D : private ::A {};

¿Es este comportamiento correcto, y si es así por qué?

Al principio pensé que era porque C hereda en privado de B lo que ocultaría las clases base. Pero si elimino la clase B "hombre medio" y solo uso esto:

class A {}; class C : private A { public: class D : private A {}; };

El error desaparece


Ejemplo de cppreference :

class A { }; class B : private A { }; class C : public B { A* p; // error: unqualified name lookup finds A as the private base of B ::A* q; // OK, qualified name lookup finds the namespace-level declaration };

Con la herencia privada, los miembros públicos y protegidos de la clase base se convierten en miembros privados de la clase derivada.

class B : private A {}; class C : private B { public: class D : private A {}; // Error because all members of A is private to B so what //would be the use of this private inheritance if you can''t access any of A''s member. };

Mientras

class D :private ::A {};

funciona porque los miembros de A se toman directamente del espacio de nombres global, lo que permite a D tener acceso a los miembros protegidos y públicos de A


Es una cuestión de alcances durante la búsqueda de nombres:

  • Cuando usas ::A es un nombre totalmente calificado, por lo tanto, te estás refiriendo explícitamente al espacio de nombres global y seleccionando A desde allí.

  • Cuando heredas de A , C (déjame decir) ve A y puedes referirte directamente al nombre A dentro de C con un nombre no calificado.

  • Cuando hereda de B , C ve B y A es privado en su alcance. Es privado, pero existe. Como A es un nombre no calificado y se busca ante todo en ese ámbito, resulta ser encontrado e inaccesible, por lo tanto, el error.


Una parte crucial para la comprensión, que no se explica explícitamente en las otras respuestas, es la siguiente:

El nombre de una clase se inyecta en el alcance de las clases.

Es decir, si tiene

class A {};

entonces puede referirse a la clase A no solo por el nombre ::A sino también por el nombre A::A Tenga en cuenta que a pesar de describir la misma clase, esos no son del mismo nombre, ya que están en diferentes ámbitos.

Ahora cuando en el ámbito de A o una clase que se deriva directa o indirectamente de A , la búsqueda no calificada encontrará A::A lugar de ::A (a menos que A::A esté oculto por otro nombre).

Además, a diferencia de otros lenguajes, C ++ no oculta los nombres privados de los ámbitos donde no puede acceder a ellos, sino que usa los especificadores de acceso solo como permiso para usar el nombre. Además, esos permisos están vinculados al nombre, no a la entidad nombrada (en este caso, la clase).

Entonces en su código, en la búsqueda no calificada de A el compilador encuentra el nombre C::B::A::A que oculta el nombre ::A , y luego verifica el permiso de acceso y encuentra que este nombre es privado en el contexto actual, ya que es un nombre en el ámbito de C::B::A que no se puede acceder desde C ya que A es una clase base privada de B


clase D: privada :: A {}; Cuando hereda de B, C ve B y A es privado en su alcance. Es privado, pero existe. Como A es un nombre no calificado y se busca ante todo en ese ámbito, resulta ser encontrado e inaccesible, por lo tanto, el error.