online - una pregunta sobre la prioridad de los operadores de C++ "dirección de" y "resolución de alcance"
operator precedence java (3)
En el primer caso, está tomando la dirección de puntero a miembro B::b
. Dado que dicho puntero NO es un miembro del padre de A
sino un objeto separado, no puede acceder a él a través del mecanismo protegido.
En el SEGUNDO caso donde funciona, está solicitando la dirección de la instancia específica de b
, calificándola con su clase base para que en el caso de herencia múltiple el compilador sepa a qué clase base se refiere. En este contexto, el atributo protegido es visible.
Tenga en cuenta que esto compila:
class B
{
protected:
int b;
};
class A : public B
{
public:
void foo(){ &A::b; } // Note here &A:: instead of &B::
};
Como ejemplo agregado, no funciona por la misma razón que el siguiente código (con suerte, más familiar) no funciona:
class B
{
protected:
int b;
};
class A : public B
{
public:
void foo(const B* b_obj) { b_obj->b; }
};
Hola, tengo este código con un error del compilador (el error es de Microsoft Visual Studio 2008):
class B
{
protected:
int b;
};
class A : public B
{
public:
void foo(){ &B::b; }// error C2248: ''B::b'' : cannot access protected member declared in class ''B''
};
Si bien este código está libre de errores:
class B
{
protected:
int b;
};
class A : public B
{
public:
void foo(){ &(B::b); }
};
Los dos fragmentos me parecen equivalentes según mi conocimiento de la precedencia de los operadores, porque :: tiene una precedencia más alta que & (vea, por ejemplo, la tabla 2 en la página 137 de "NORMAS COMUNES CONTRA EL VEHÍCULO AÉREO C ++ NORMAS DE CODIFICACIÓN PARA EL DESARROLLO DEL SISTEMA Y PROGRAMA DE DEMOSTRACIÓN " http://www2.research.att.com/~bs/JSF-AV-rules.pdf )
Pero son diferentes ... Creo que es algo relacionado con "puntero a miembro de datos" pero no sé cómo encaja con la precedencia de los operadores.
Alguna explicacion
Gracias Alessandro
Esto es sólo una suplementación.
§5.3.1 / 2 dice:
El resultado del operador unario y es un puntero a su operando. El operando será un lvalue o un id-calificado. En el primer caso, si el tipo de expresión es "T", el tipo del resultado es "puntero a T." ...
Para un id-calificado, ... Si el miembro es un miembro no estático de la clase C del tipo T, el tipo del resultado es "puntero al miembro de la clase C del tipo T."
De acuerdo con §5.1 / 7, B::b
incluye en el caso de id-calificado, pero (B::b)
no lo hace. Entonces, el compilador lo interpreta como un lvalue.
La diferencia entre las dos afirmaciones se vuelve más obvia cuando intenta devolver el valor:
int* foo() { return &(B::b);} // This is a pointer to an int
int A::* foo() { return &B::b; } // This is a pointer to a member of type int
Lo que quieres hacer es acceder a través del objeto A:
int A::* foo() { return &A::b; } // This is a pointer to a member of type int
A partir de la A se le permite acceder.
Accediendo a él a través de B es como acceder desde el exterior y, por lo tanto, activa los especificadores de acceso.