2012-04-05 28 views
7

Tengo la siguiente consulta;Herencia y acceso a la amistad. C++

classB inherits from classA 
classC is friend of classB 

¿No significa que la clase C debería poder acceder a los miembros protegidos de la clase A? Como classB hereda esto de classA, un classC puede acceder a todo en la clase classB?

Respuesta

6

Esto significa que classC debe ser capaz de acceder a la parte protegida de subobjeto classAclassB. Debe no ser capaz de acceder a cualquier elemento no público desde classA sí mismo.

Por ejemplo:

class C; 

class A 
{ 
protected: 
    int i; 
}; 

class B: 
    public A 
{ 
    friend class C; 
}; 

class C 
{ 
public: 
    void foo(A& a, B& b) 
    { 
    // a.i = 3; // not allowed 
    b.i = 3; // allowed, accesses the `i` of the `A` subobject of `B` 
    } 
}; 
+0

Esta es la mejor respuesta para la pregunta original. –

+0

@KerrekSB: Gracias. – celtschk

8

[Mi respuesta original no tenía sentido. Disculpas por eso. Gracias a @celtschk por señalarlo y proporcionar la mejor respuesta.]

Si C es un amigo de B, se puede acceder a todos los miembros B 's, ya sea privada, pública o protegida, y que incluye la accesibles miembros (públicos y protegidos) que forman parte de un subobjeto de base:

struct A { protected: int a; }; 
struct B : A { private: int b; friend struct C; } 

struct C 
{ 
    B x; 
    A w; 

    void f() 
    { 
     x.a = 1; // fine 
     x.b = 2; // fine 

     // w.a = 0; /* Error, #1 */ 
    } 

    friend struct D; // see below 
}; 

sin embargo, la amistad no es ni transitiva ni heredada: C es un amigo de B, pero no de A (ver # 1). Además, si D es un amigo de C, entonces D no hay nada del acceso que C 's amistad a B permite que, por lo D no pueden acceder a B' s miembros no públicos. Del mismo modo, si struct E : C hereda de C, entonces E tampoco es amigo de B automáticamente:

struct D 
{ 
    B y; 
    void g() 
    { 
     // y.b = 3; /* Error! */ 
    } 
}; 

struct E : C 
{ 
    B z; 
    void h() 
    { 
     // y.b = 4; /* Error! */ 
    } 
} 

Tal vez se puede resumir lo que está pasando en algunos puntos:

  • Una clase derivada tiene acceso a todos los miembros públicos y protegidos de cada clase base.

  • Un amigo de una clase tiene acceso a todos los miembros de esa clase a los que tiene acceso (es decir, todos los miembros que excluyen miembros de base privados).

  • La amistad no se hereda: si una clase tiene un amigo, esa amistad no se aplica a ninguna de sus clases base ni a ninguna de sus clases derivadas.

  • Un amigo de un amigo no es un amigo.

+0

También se puede acceder a los miembros protegidos de '' A' subobjeto de B'. Simplemente no puede acceder a miembros protegidos de objetos arbitrarios 'A' (pero tampoco puede' B'). – celtschk

+0

@celtschk: Creo que mi respuesta es completamente incorrecta. Necesito revisarlo. –

+0

Todavía no es del todo correcto: por supuesto, solo puede acceder a los miembros del subobjeto 'A' al que puede acceder' B'. Tal como está escrito, también debe tener acceso a los miembros privados de 'A'. – celtschk