2011-02-16 2 views
23

안녕하세요 컴파일러 오류 (오류가 마이크로 소프트 비주얼 스튜디오 2008입니다)이 코드가 있습니다와 "범위 해상도", "주소"C++ 사업자의 우선 순위에 대한 질문

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' 
}; 

이 코드는 동안을 무료 오류 : ::이 &보다 높은 우선 순위를 가지고 있기 때문에

class B 
{ 
protected: 
int b; 
}; 

class A : public B 
{ 
public: 
void foo(){ &(B::b); } 
}; 

두 조각

는 사업자의 우선 순위의 내 지식을 기반으로 나 동등한 것 (JOINT STRIKE 파이터 "의 137 페이지에 예를 표 2 참조 시스템 개발을위한 AIR VEHICLE C++ 코딩 표준 A ND DEMONSTRATION PROGRAM " http://www2.research.att.com/~bs/JSF-AV-rules.pdf)

그러나 이것들은 ..."데이터에 대한 포인터 "와 관련이 있지만 연산자 우선 순위에 어떻게 부합하는지 알지 못합니다.

설명이 있으십니까?

는 포인터 - 투 - 회원 B::b의 주소를 가지고있는 첫 번째 경우, 알레산드로

+0

우선 순위가 잘못되면 어쨌든 확실하게 (다른) 구문 오류가 발생합니까? – Flexo

+2

차이점에 주목하자 :'int * i = & (A :: b);'그러나 int A :: * m = &A::b;' –

답변

13

을 주셔서 감사합니다. 이러한 포인터는 A의 부모 멤버가 아니고 별도의 개체이기 때문에 보호 된 메커니즘을 통해 액세스 할 수 없습니다. 이 컴파일러는 당신이 의미하는 기본 클래스 알게 될 것입니다 다중 상속의 경우 있도록 기본 클래스로 자격의 특정 인스턴스b의의 주소를 요구하고 작동하는 두 번째 경우

. 이 컨텍스트에서는 보호 된 속성을 볼 수 있습니다.

참고이 컴파일합니다 :

class B 
{ 
protected: 
int b; 
}; 

class A : public B 
{ 
public: 
void foo(const B* b_obj) { b_obj->b; } 
}; 
+1

'& this-> B :: b;' –

+0

@Gene Bushuyev Right 이것은 OP의 두 번째 (작동중인) 예제와 정확히 동일합니다. 일반적인 포인터 대 멤버가 아니라 부모의 특정 'b'멤버의 주소를 가져옵니다. –

+2

표준에서 구문 및 차이점에 대해 언급 한 모든 참조는 무엇입니까? 이 구문'& (B :: b)'는'b'가'A'의 특정 인스턴스에 속하는 것을 어떻게 의미합니까? – Nawaz

6

다음 (잘하면 더 익숙한) 코드가 작동하지 않습니다이 같은 이유로 작동하지 않는 추가 예를 들어

class B 
{ 
protected: 
int b; 
}; 

class A : public B 
{ 
public: 
void foo(){ &A::b; } // Note here &A:: instead of &B:: 
}; 

두 문 사이의 차이는 값을 반환하려고 시도 할 때 더욱 분명 해집니다.

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 

A 개체를 통해 액세스하려면 다음을 수행하십시오.

int A::* foo() { return &A::b; } // This is a pointer to a member of type int 

마찬가지로 A에서 액세스 할 수 있습니다.
B를 통해 액세스하는 것은 외부에서 액세스하므로 액세스 지정자를 트리거합니다.

+0

이것은 제 의견으로는 차이점을 더 잘 설명합니다. +1 – Nawaz

+0

"B를 통해 액세스하는 것은 외부에서 액세스하므로 액세스 지정자를 트리거합니다." 맞지 않다고 생각합니다. OP의 두 번째 예제는 그것을 증명합니다. 또한, A가'b' shadowing B :: b'라는 또 다른 속성을 포함하고 있다고 상상해보십시오. 그런 다음'& (A :: b)'와'& (B :: b)'를 사용하여 구분할 수 있습니다. –

+0

@ Tilman Vogel : 나는 동의하지 않는다. 이것이 내가 and 연산자에 의해 실제로 생성되는 것에 의해 양자가 어떻게 구별되는지 위에 보여준 이유입니다. 참조 용으로 –

7

이것은 보충하기위한 것입니다.
§5.3.1/2라고 :

& 단항 연산자의 결과는 피연산자 포인터 이다. 피연산자 은 lvalue 또는 qualified-id 여야합니다. 식의 형태 인 경우는 제 경우, "T"에서는 결과의 종류가 규정 -ID를 ...
"T. 포인터"이다 ..회원이 타입의 클래스 C T의 비 정적 부재 인 경우 결과의 종류는 §5.1/7 항

"형 T.의 클래스 C의 멤버에 대한 포인터 "인 B::b은 정규화 ID 케이스에 해당하지만 (B::b)은 그렇지 않습니다. 그래서 컴파일러는 이것을 lvalue로 해석합니다.

+0

+1. 이제 조금 더 명확 해졌습니다! – Nawaz