Program Club

상속 : 'A'는 'B'의 액세스 할 수없는 기반입니다.

proclub 2020. 10. 14. 21:26
반응형

상속 : 'A'는 'B'의 액세스 할 수없는 기반입니다.


$ cat inheritance.cpp 
#include <iostream>

using namespace std;

class A { };
class B : private A { };

int main() {
    A* ab = new B;
}
$
$ g++ inheritance.cpp
inheritance.cpp: In function 'int main()':
inheritance.cpp:9: error: 'A' is an inaccessible base of 'B'
$

이 오류를 이해하지 못합니다.

내가 이해 하고이 자습서에서 확인 했듯이 private상속은의 구성원이 class B외부 세계에 표시되는 방식 만 변경해야합니다 .

개인 지정자는 class B여기서 멤버의 가시성을 변경하는 것 이상을 수행하고 있다고 생각합니다 .

  • 이 오류는 무엇이며 그 의미는 무엇입니까?
  • 기본적으로 C ++에서 이러한 유형의 코드를 허용하는 것이 잘못된 것은 무엇입니까? 완전히 무해 해 보입니다.

상속을 비공개로 설정하면 기본적으로 B가 A에서 상속한다는 사실조차도 외부 세계에 접근하거나 볼 수없는 비공개라는 것입니다.

그것이 허용된다면 어떤 일이 일어날 지에 대한 장황한 논의를하지 않고, 단순한 사실은 그것이 허용되지 않는다는 것입니다. 파생 된 형식의 개체를 참조하기 위해 기준에 대한 포인터를 사용하려는 경우 공용 상속을 사용하는 데 거의 어려움이 있습니다.

개인 상속은 없습니다 반드시 (또는 보통)을 수행하도록 구성 Liskov 대체 원칙을 . 공용 상속은 파생 된 개체가 기본 클래스의 개체로 대체 될 수 있다고 주장하며 적절한 의미 체계 계속 생성됩니다. 그러나 개인 상속은 그것을 주장 하지 않습니다 . 개인 상속에 의해 암시되는 관계에 대한 일반적인 설명은 "다음으로 구현 됨"입니다.

공용 상속이란 파생 클래스가 기본 클래스의 모든 기능을 유지하고 잠재적으로 추가 기능을 추가한다는 것을 의미합니다. 개인 상속은 종종 그 반대를 의미합니다. 파생 클래스는 일반 기본 클래스를 사용하여 더 제한된 인터페이스로 무언가를 구현합니다.

예를 들어, C ++ 표준 라이브러리의 컨테이너가 템플릿이 아닌 상속을 사용하여 구현되었다고 가정 해 보겠습니다. 현재 시스템에서, std::dequestd::vector용기이며, std::stack보다 제한된 인터페이스를 제공하는 컨테이너 어댑터이다. 템플릿을 기반으로하기 때문에 또는에 std::stack대한 어댑터로 사용할 수 있습니다 .std::dequestd::vector

본질적으로 동일한 상속을 제공하려면 개인 상속을 사용할 std::stack것이므로 다음과 같습니다.

class stack : private vector {
    // ...
};

이 경우, 우리는 확실히 않습니다 하지 사용자가 우리를 조작 할 수 있도록하려면 stack그것 인 것처럼 vector. 그렇게하면 스택의 기대치를 위반할 수 있습니다 (예 : 사용자가 의도 한대로 순전히 스택과 같은 방식이 아닌 중간에 항목을 삽입 / 제거 할 수 있음). 우리는 기본적으로 사용하고있는 vector우리의 스택을 구현하는 편리한 방법으로하지만, (예를 들어) 우리의 구현 변경 한 경우 stack또는 (NO 기본 클래스에 대한 의존도와) 독립을 측면에서 그것을 다시 구현 std::deque, 우리는 할 수 없습니다 것을 원하는 클라이언트 코드에 영향을 미치기 위해 클라이언트 코드에 대해 이것은 특수한 다양한 벡터 (또는 데크)가 아닌 스택이어야합니다.


개인 상속은 클래스 B의 구성원이 외부 세계에 표시되는 방식 만 변경해야합니다.

그렇습니다. 그리고 만약

A* p = new B;

허용 된 후 어떤의 상속 된 멤버는 B단지함으로써, 외부에서 액세스 할 수 있습니다 A*. 그들은 개인적으로 상속되기 때문에 그 액세스는 불법이며 업 캐스트도 마찬가지입니다.


clang++ 약간 더 이해하기 쉬운 오류 메시지를 제공합니다.

example.cpp:9:13: error: cannot cast 'B' to its private base class 'A'
    A* ab = new B;
            ^
example.cpp:6:11: note: declared private here
class B : private A { };
          ^~~~~~~~~
1 error generated.

저는 C ++ 전문가는 아니지만 단순히 허용되지 않는 것 같습니다. 사양을 살펴보고 어떤 결과가 나오는지 살펴 보겠습니다.

편집 : 여기에 사양-섹션 4.10 포인터 변환 , 단락 3 의 관련 참조가 있습니다 .

A prvalue of type "pointer to cv D", where D is a class type, can be converted to a prvalue of type "pointer to cv B", where B is a base class of D. If B is an inaccessible or ambiguous base class of D, a program that necessitates this conversion is ill-formed.


It's pretty simple: the fact that A is inherited privately means that the fact that B extends A is a secret, and only B "knows" it. That is the very definition of private inheritance.


Private inheritance means that outside the derived class, the inheritance information is hidden. That means you can't cast the derived class to the base class: the relationship isn't known to the caller.

참고URL : https://stackoverflow.com/questions/9661936/inheritance-a-is-an-inaccessible-base-of-b

반응형