부모 수업의 보호 된 데이터는 아동 수업에서 사용할 수 없습니까?

StackOverflow https://stackoverflow.com/questions/1414506

  •  06-07-2019
  •  | 
  •  

문제

나는 혼란 스럽다 : 나는 보호 된 데이터가 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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top