[c++] 개인, 공용 및 보호 된 상속의 차이점

차이점은 무엇이며 public, private그리고 protected상속 C ++는?

SO에서 찾은 모든 질문은 특정 사례를 처리합니다.



답변

이 질문에 대답하기 위해 먼저 회원의 접근자를 내 말로 설명하고 싶습니다. 이미 알고 있다면 “다음 :”으로 넘어가십시오.

거기에 제가 알고 세 가지 접근은 다음과 같습니다 public, protected그리고 private.

허락하다:

class Base {
    public:
        int publicMember;
    protected:
        int protectedMember;
    private:
        int privateMember;
};
  • 알고있는 모든 것은 Base또한 Base포함하는 것을 알고 있습니다 publicMember.
  • 만 어린이들 (자녀)은 알고 있습니다 Base포함되어 있습니다 protectedMember.
  • 아무도하지만 Base알고 없습니다 privateMember.

“알다”는 것은 “존재 함을 인정하고 따라서 접근 할 수 있음”을 의미합니다.

다음:

공개, 개인 및 보호 된 상속에서도 마찬가지입니다. 에서 상속되는 클래스 Base와 클래스 Child를 생각해 봅시다 Base.

  • 상속이 public인지 Base하고 알고있는 모든 것이 상속 ChildChild받는 경우 Base.
  • 상속이 protected유일한 Child경우에 그 하위 항목은 상속을 인식합니다 Base.
  • 상속이 private인 경우 상속을 Child알고있는 사람 외에는 아무도 없습니다 .

답변

class A 
{
public:
    int x;
protected:
    int y;
private:
    int z;
};

class B : public A
{
    // x is public
    // y is protected
    // z is not accessible from B
};

class C : protected A
{
    // x is protected
    // y is protected
    // z is not accessible from C
};

class D : private A    // 'private' is default for classes
{
    // x is private
    // y is private
    // z is not accessible from D
};

중요 참고 : 클래스 B, C 및 D는 모두 변수 x, y 및 z를 포함합니다. 접근의 문제 일뿐입니다.

보호 및 개인 상속 사용에 대해서는 여기를 참조하십시오 .


답변

상속의 가시성을 제한하면 코드에서 일부 클래스가 다른 클래스를 상속 함을 알 수 없습니다. 파생에서 기본으로의 암시 적 변환은 작동하지 않으며 기본에서 파생으로의 암시 적 변환도 작동 static_cast하지 않습니다.

클래스의 멤버 / 친구 만 개인 상속을 볼 수 있으며 멤버 / 친구 및 파생 클래스 만 보호 된 상속을 볼 수 있습니다.

공공 상속

  1. IS-A 상속. 버튼은 윈도우이며, 윈도우가 필요한 곳이면 버튼도 전달할 수 있습니다.

    class button : public window { };

보호 된 상속

  1. 기간 내에 보호됩니다. 거의 유용하지 않습니다. boost::compressed_pair빈 클래스에서 파생되고 빈 기본 클래스 최적화를 사용하여 메모리를 절약하는 데 사용됩니다 (아래 예에서는 템플릿을 사용하여 해당 지점을 계속 유지하지 않음).

    struct empty_pair_impl : protected empty_class_1 
    { non_empty_class_2 second; };
    
    struct pair : private empty_pair_impl {
      non_empty_class_2 &second() {
        return this->second;
      }
    
      empty_class_1 &first() {
        return *this; // notice we return *this!
      }
    };
    

개인 상속

  1. 이용 약관. 기본 클래스의 사용법은 파생 클래스를 구현하기위한 것입니다. 특성과 크기가 중요한 경우에 유용합니다 (함수 만 포함 된 빈 특성은 ​​빈 기본 클래스 최적화를 사용합니다). 그러나 종종 격리 가 더 나은 솔루션입니다. 문자열의 크기는 매우 중요하므로 여기에서 자주 볼 수 있습니다.

    template<typename StorageModel>
    struct string : private StorageModel {
    public:
      void realloc() {
        // uses inherited function
        StorageModel::realloc();
      }
    };
    

공개 회원

  1. 골재

    class pair {
    public:
      First first;
      Second second;
    };
    
  2. 접근 자

    class window {
    public:
        int getWidth() const;
    };
    

보호 회원

  1. 파생 클래스에 대한 향상된 액세스 제공

    class stack {
    protected:
      vector<element> c;
    };
    
    class window {
    protected:
      void registerClass(window_descriptor w);
    };
    

개인 회원

  1. 구현 세부 사항 유지

    class window {
    private:
      int width;
    };
    

C 스타일 캐스트는 정의 된 안전한 방식으로 파생 클래스를 보호 또는 개인 기본 클래스로 캐스트하고 다른 방향으로도 캐스트 할 수 있습니다. 구현 세부 사항에 따라 코드를 만들 수 있기 때문에 모든 비용을 피해야하지만 필요한 경우이 기술을 사용할 수 있습니다.


답변

이 세 키워드는 또한 완전히 다른 상황에서 가시성 상속 모델 을 지정하는 데 사용됩니다 .

이 테이블은 서브 클래스가 완전히 정의 될 때 컴포넌트에 대한 결과 액세스를 나타내는 컴포넌트 선언 및 상속 모델의 가능한 모든 조합을 수집합니다.

여기에 이미지 설명을 입력하십시오

위의 표는 다음과 같이 해석됩니다 (첫 번째 행을보십시오).

구성 요소가되는 경우 선언 으로 대중 과 그 클래스가되어 상속 으로 공공 결과 액세스 입니다 공공 .

예를 들면 :

 class Super {
    public:      int p;
    private:     int q;
    protected:   int r;
 };

 class Sub : private Super {};

 class Subsub : public Sub {};

변수에 대한 결과 액세스 p, q, r수업 시간에 Subsub는 없다 아무도 .

또 다른 예:

class Super {
    private:     int x;
    protected:   int y;
    public:      int z;
 };
class Sub : protected Super {};

Sub 클래스의 변수 y에 대한 결과 액세스 는 보호 되며 variable 에 대한 액세스 는 없습니다 .zx

더 자세한 예 :

class Super {
private:
    int storage;
public:
    void put(int val) { storage = val;  }
    int  get(void)    { return storage; }
};
int main(void) {
    Super object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

이제 서브 클래스를 정의하자 :

class Sub : Super { };

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

명명 된 클래스의 서브 클래스 Super또는 해당 Sub클래스 의 서브 클래스 인 Sub이라는 정의 된 클래스는 클래스 에서 파생됩니다 Super. 이 Sub클래스는 새로운 변수 나 새로운 함수를 도입하지 않습니다. 그것은 Sub클래스의 객체가 Super클래스가 실제로 Super클래스 객체 의 사본이 된 후에 모든 특성을 상속 한다는 것을 의미합니까 ?

없음 . 그렇지 않습니다.

다음 코드를 컴파일하면 컴파일 오류 putget메소드에 액세스 할 수 없다는 컴파일 오류 만 표시 됩니다. 왜?

가시성 지정자를 생략하면 컴파일러는 소위 개인 상속 을 적용한다고 가정합니다 . 이는 모든 퍼블릭 슈퍼 클래스 컴포넌트가 프라이빗 액세스 로 바뀌고 프라이빗 슈퍼 클래스 컴포넌트는 전혀 액세스 할 수 없음을 의미합니다. 따라서 서브 클래스 내에서 후자를 사용할 수 없음을 의미합니다.

우리는 이전에 사용 된 액세스 정책을 보존하고 싶다고 컴파일러에 알려야합니다.

class Sub : public Super { };

오해하지 마십시오 : 스토리지 변수와 같은 Super 클래스의 개인 구성 요소가 다소 마술적인 방식으로 공개 구성 요소로 바뀐다는 의미는 아닙니다. 비공개 구성 요소는 비공개로 유지 되며 공개
공개 상태로 유지 됩니다.

Sub클래스의 객체는 클래스에서 생성 된 이전 형제와 같은 것을 “거의”수행 할 수 있습니다 Super. “거의” 서브 클래스라는 사실은 클래스가 슈퍼 클래스의 개인 컴포넌트에 대한 액세스 권한을 상실 했음을 의미하기 때문 입니다. Sub저장 변수를 직접 조작 할 수 있는 클래스 의 멤버 함수를 작성할 수 없습니다 .

이것은 매우 심각한 제한 사항입니다. 해결 방법이 있습니까?

.

세 번째 액세스 수준을 protected 라고 합니다. protected 키워드 는 서브 클래스에서 사용될 때이 컴포넌트로 표시된 컴포넌트 가 공용 컴포넌트 처럼 작동하며 다른 세계에서는 개인 컴포넌트 처럼 보입니다 . – 이 (우리의 예에서 슈퍼 클래스와 같은)만을 공개적으로 상속 클래스 마찬가지입니다

class Super {
protected:
    int storage;
public:
    void put(int val) { storage = val;  }
    int  get(void)    { return storage; }
};

class Sub : public Super {
public:
    void print(void) {cout << "storage = " << storage;}
};

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get() + 1);
    object.print();
    return 0;
}

예제 코드에서 알 수 있듯이 Sub클래스에 대한 새로운 기능 이며 한 가지 중요한 작업 을 수행합니다. Super 클래스에서 스토리지 변수에 액세스합니다 .

변수가 private으로 선언되면 불가능합니다. 기본 함수 범위에서 변수는 어쨌든 숨겨져 있으므로 다음과 같이 작성하면 다음과 같습니다.

object.storage = 0;

컴파일러는 그것이임을 알려줍니다 error: 'int Super::storage' is protected.

마지막으로 마지막 프로그램은 다음과 같은 출력을 생성합니다.

storage = 101


답변

기본 클래스의 공개 멤버가 파생 클래스에서 노출되는 방법과 관련이 있습니다.

  • 공개-> 기본 클래스의 공개 멤버는 공개 (일반적으로 기본값)입니다.
  • protected-> 기본 클래스의 공개 멤버가 보호됩니다
  • 비공개-> 기본 클래스의 공개 멤버는 비공개입니다

litb가 지적했듯이 공개 상속은 대부분의 프로그래밍 언어에서 볼 수있는 전통적인 상속입니다. 그것은 “IS-A”관계를 모형화 한 것입니다. C ++ 특유의 AFAIK 인 사유 상속은 “기간 내에 구현 된”관계입니다. 즉 , 파생 클래스에서 공용 인터페이스 를 사용 하려고 하지만 파생 클래스의 사용자가 해당 인터페이스에 액세스하지 못하도록해야합니다. 많은 경우,이 경우 기본 클래스를 개인 기본으로 사용하는 대신 기본 클래스를 집계해야 기본 클래스의 기능을 재사용하기 위해 파생 된 멤버를 작성해야합니다.


답변

Member in base class : Private   Protected   Public   

상속 유형 :              상속 된 객체 :

Private            :   Inaccessible   Private     Private
Protected          :   Inaccessible   Protected   Protected
Public             :   Inaccessible   Protected   Public


답변

1) 공공 상속 :

ㅏ. 파생 클래스에서는 기본 클래스의 비공개 멤버에 액세스 할 수 없습니다.

비. 기본 클래스의 보호 멤버는 파생 클래스에서 보호됩니다.

씨. 기본 클래스의 공개 멤버는 파생 클래스에서 공개로 유지됩니다.

따라서 다른 클래스는 파생 클래스 개체를 통해 Base 클래스의 공용 멤버를 사용할 수 있습니다.

2) 상속 상속 :

ㅏ. 파생 클래스에서는 기본 클래스의 비공개 멤버에 액세스 할 수 없습니다.

비. 기본 클래스의 보호 멤버는 파생 클래스에서 보호됩니다.

씨. Base 클래스의 공개 멤버도 파생 클래스의 보호 멤버가됩니다.

따라서 다른 클래스는 파생 클래스 개체를 통해 Base 클래스의 공용 멤버를 사용할 수 없습니다. 그러나 Derived의 서브 클래스에서 사용할 수 있습니다.

3) 개인 상속 :

ㅏ. 파생 클래스에서는 기본 클래스의 비공개 멤버에 액세스 할 수 없습니다.

비. 기본 클래스의 보호 및 공개 멤버는 파생 클래스의 개인 멤버가됩니다.

따라서 파생 클래스에서 개인 클래스이므로 파생 클래스 개체를 통해 다른 클래스에서 Base 클래스의 멤버에 액세스 할 수 없습니다. 따라서 파생 클래스의 하위 클래스조차도 액세스 할 수 없습니다.