2010-06-13 14 views
5

Puede explicar por qué esto no está permitido,C++ herencia: la determinación del alcance y la visibilidad de los miembros

#include <stdio.h> 

class B { 
private: 
    int a; 
public: 
    int a; 
}; 

int main() { 
    return 0; 
} 

mientras que es esto?

#include <stdio.h> 

class A { 
public: 
    int a; 
}; 

class B : public A{ 
private: 
    int a; 
}; 

int main() { 
    return 0; 
} 

En los dos casos, tenemos una pública y otra variable privada denominada a en class B.


editado ahora!

+0

@Neil: ¿Quiere decir que el 2º declara una Clase A? – Alan

+1

@ Alan Sí, estaba tan desconcertado por la pregunta que me confundí un poco :-) –

+3

¿Por qué esto tiene un voto en contra? Es una pregunta razonable, recuerdo haberme preguntado lo mismo al aprender clases en C++ ... – Cam

Respuesta

15

En los dos casos, tenemos una pública y una variable privada denominada en una clase B.

No, eso no es cierto.

En el primer caso, no puede tener dos identificadores con el mismo nombre en el mismo ámbito. Mientras que en el segundo caso, B::a esconde A::a, y para acceder a A::a usted tiene que calificar totalmente el nombre:

Clase B
b.a = 10; // Error. You can't access a private member. 
b.A::a = 10; // OK. 
0

El primero no está permitido porque conduce a definiciones ambiguas. En la segunda, aunque tenga una variable entera pública y una a entera, ha ocultado A :: a dentro de su clase B. El compilador sabe implícitamente lo que quiere porque hay una forma de acceder explícitamente a las variables ocultas.

También creo que se reduce a nombrar mangaling: los especificadores de almacenamiento no terminan como parte del nombre real. Sin embargo, podría estar equivocado en esto.

La manera más fácil de ilustrar por qué uno está permitido y por qué el otro no lo es, es ver cómo compila el compilador una función miembro que usa cada variable.

Dentro de su clase b:

class b { 

int a; 
public: 
int a; 

void myMethod() 
{ 
a = 10; //what a should the compiler use? Ambiguous, so the compiler sez BZZT. 
} 

} 

Para el segundo ejemplo:

class A 
{ 
public: 
int a; 
} 

class B: public A 
{ 
private: 
int a; 

void someMethod() 
{ 
a = 10; //implied that you are using B::a (which may be a programmer error) 

} 

} 
+0

perdón por eso. editado ahora! – Moeb

3

Debido B::aescondeA::a en el segundo ejemplo. Aún puede acceder a él, pero necesita una calificación explícita para que el compilador descubra que está solicitando el miembro de la clase principal con el mismo código.

En el primer ejemplo, ambos a están en el mismo ámbito, mientras que en el segundo ejemplo los ámbitos son diferentes.

0

en el primer ejemplo no es válido debido a que C++ no puede distinguir a los miembros de sus especificadores de acceso (públicas/privado/protegido). Sin embargo, los espacios de nombres son una forma para que C++ distinga a los miembros. En la clase B del segundo código, no tiene una "pública a" y una "privada a", tiene B::a y A::a.

Incluso si se permitiera declarar miembros del mismo nombre/firma con diferentes especificadores de acceso, no habría forma de dirigirse al miembro correcto.

Cuestiones relacionadas