부모 수업의 보호 된 데이터는 아동 수업에서 사용할 수 없습니까?
문제
나는 혼란 스럽다 : 나는 보호 된 데이터가 C ++의 주어진 클래스의 어린이들에 의해 읽거나 쓸 수 있다고 생각했다.
아래 스 니펫은 MS 컴파일러에서 컴파일하지 못합니다
class A
{
protected:
int data;
};
class B : public A
{
public:
B(A &a)
{
data = a.data;
}
};
int main()
{
A a;
B b = a;
return 0;
}
에러 메시지:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
demoFail.cpp
demoFail.cpp(12) : error C2248: 'A::data' : cannot access protected member declared in class 'A'
demoFail.cpp(4) : see declaration of 'A::data'
demoFail.cpp(2) : see declaration of 'A'
내가 뭘 잘못하고 있죠?
해결책
TC ++ PL에 따르면, pg 404 :
파생 클래스는 자체 유형의 객체에 대해서만 기본 클래스의 보호 멤버에 액세스 할 수 있습니다 ... 이는 파생 된 클래스가 다른 파생 클래스에 속하는 데이터를 손상시킬 때 발생하는 미묘한 오류를 방지합니다.
물론 여기에 귀하의 경우이를 해결하는 쉬운 방법이 있습니다.
class A
{
protected:
int data;
};
class B : public A
{
public:
B(const A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}
다른 팁
C ++ 표준은 보호 된 비 정적 회원에 대해 말합니다. 11.5/1
파생 클래스의 친구 또는 멤버 함수가 보호 된 비 종교적 멤버 함수 또는 기본 클래스의 보호 된 비 종교적 데이터 구성원을 참조하는 경우, 액세스 점검은 11 절에 이전에 설명 된 것 외에도 적용됩니다 (5.3). .1), 액세스는 파생 클래스 자체 (또는 해당 클래스에서 파생 된 클래스)의 포인터, 참조 또는 객체를 통해 이루어져야합니다 (5.2.5). 액세스가 멤버에 대한 포인터를 형성하는 경우, 중첩 이름 사례는 파생 클래스 (또는 해당 클래스에서 파생 된 클래스)의 이름을 지정해야합니다.
다른 사람이 이전에 언급 한 것을 고치는 것 외에도 (생성자 B
개인), 나는 rlbond의 방식이 잘할 것이라고 생각합니다. 그러나 표준의 위 단락의 직접적인 결과는 다음과 같은 멤버 포인터를 사용하여 다음이 가능하다는 것입니다.
class B : public A {
public:
B(A &a){
int A::*dataptr = &B::data;
data = a.*dataptr;
}
};
물론이 코드는 권장하지는 않지만 ~할 수 있다 실제로 필요한 경우 (이 방법으로 인쇄하는 데 사용되는 것을 보았습니다. std::stack
, std::queue
, std::priority_queue
보호 된 컨테이너 멤버에 액세스함으로써 c
)
방금 그렇지 않아야합니다 an A
a B
건설자. 의도는 초기화를 떠나는 것입니다 A
자체 생성자의 구성원 :
struct A {
A( const A& a ): data( a.data ) {}
protected: int data;
};
struct B : public A {
B( const A& a ): A( a ) {}
};
B의 생성자는 개인입니다. 클래스에서 아무것도 지정하지 않으면 기본 수정자는 비공개입니다 (Structs의 경우 공개). 따라서이 예에서 문제는 B를 구성 할 수 없다는 것입니다. B anoter 문제가 발생합니다.
B는이 경우에 파생 된 부분을 수정할 권리가 있지만이 경우 A와 마찬가지로 A와 비슷하지 않습니다.
다음을 수행 할 수 있습니다.
class A
{
public:
A()
: data(0)
{
}
A(A &a)
{
data = a.data;
}
protected:
int data;
};
class B : public A
{
public:
B(A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}