programing tip

개인, 공용 및 보호 상속의 차이점

itbloger 2020. 9. 28. 08:25
반응형

개인, 공용 및 보호 상속의 차이점


차이점은 무엇이며 public, private그리고 protectedC에서 상속 ++? 내가 찾은 모든 질문은 특정 사례를 다룹니다.


이 질문에 답하기 위해 먼저 회원의 접근자를 제 말로 설명하고 싶습니다. 이미 알고있는 경우 "다음 :"제목으로 건너 뜁니다.

내가 알고있는 세 가지 접근자가 있습니다 : public, protectedprivate.

허락하다:

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

"알고있다"는 것은 "의 존재를 인정하고 따라서 액세스 할 수있다"는 의미입니다.

다음:

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

  • 상속 인 경우 public, 알고 모든 것을 Base하고 Child또한 알고 Child상속에서 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 스타일 캐스트는 의도적으로 파생 클래스를 정의되고 안전한 방식으로 보호 또는 개인 기본 클래스로 캐스팅하고 다른 방향으로도 캐스팅 할 수 있도록 허용합니다. 구현 세부 사항에 따라 코드가 달라 지도록 만들 수 있기 때문에 모든 비용을 들이지 않아야하지만 필요한 경우이 기술을 사용할 수 있습니다.


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

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

litb가 지적했듯이 공용 상속은 대부분의 프로그래밍 언어에서 볼 수있는 전통적인 상속입니다. 그것은 "IS-A"관계의 모델입니다. C ++ 특유의 AFAIK 인 사적 상속은 "IMPLEMENTED IN TERMS OF"관계입니다. , 파생 클래스에서 공용 인터페이스 사용 하고 싶지만 파생 클래스의 사용자가 해당 인터페이스에 액세스하는 것을 원하지 않습니다. 많은 사람들은이 경우 기본 클래스를 집계해야한다고 주장합니다. 즉, 기본 클래스를 전용 기본으로 사용하는 대신 기본 클래스의 기능을 재사용하기 위해 파생 된 멤버를 만들어야합니다.


이 세 키워드는 가시성 상속 모델 을 지정하기 위해 완전히 다른 컨텍스트에서도 사용됩니다 .

이 테이블은 하위 클래스가 완전히 정의되었을 때 구성 요소에 대한 결과 액세스를 제공하는 구성 요소 선언 및 상속 모델의 가능한 모든 조합을 수집합니다.

여기에 이미지 설명 입력

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

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

예 :

 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대한 결과 액세스 보호 되고 변수 대한 액세스 none 입니다.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후에 모든 특성을 상속 한다는 의미 입니까?SuperSuper

아니 . 그렇지 않습니다.

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

가시성 지정자를 생략하면 컴파일러는 소위 개인 상속 을 적용 할 것이라고 가정합니다 . 이는 모든 공용 슈퍼 클래스 구성 요소가 개인 액세스 로 바뀌고 개인 슈퍼 클래스 구성 요소에 전혀 액세스 할 수 없음을 의미합니다. 결과적으로 하위 클래스 내에서 후자를 사용할 수 없음을 의미합니다.

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

class Sub : public Super { };

오해하지 마십시오 . Super 클래스의 개인 구성 요소 (저장 변수와 같은)가 다소 마술적인 방식으로 공용 구성 요소로 바뀐다는 의미는 아닙니다. 개인 구성 요소는 유지됩니다 개인 , 대중은 유지됩니다 공개 .

Sub클래스의 객체는 클래스에서 생성 된 이전 형제 자매와 "거의"동일한 작업을 수행 할 수 있습니다 Super. "거의" 하위 클래스라는 사실은 클래스가 수퍼 클래스의 개인 구성 요소에 대한 액세스 권한을 잃었 음을 의미하기 때문 입니다. Sub스토리지 변수를 직접 조작 할 수 있는 클래스 의 멤버 함수를 작성할 수 없습니다 .

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

.

세 번째 액세스 수준을 protected 라고 합니다. protected 키워드는 그것으로 표시된 컴포넌트 가 어떤 서브 클래스에 의해 사용될 때 공용 컴포넌트 처럼 동작하고 나머지 세계에서는 개인용 컴포넌트 처럼 보인다는 것을 의미합니다 . - 이것은 공개적으로 상속 된 클래스에만 해당됩니다 (예 : Super 클래스) .

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.

Finally, the last program will produce the following output:

storage = 101

Member in base class : Private   Protected   Public   

Inheritance type :             Object inherited as:

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

1) Public Inheritance:

a. Private members of Base class are not accessible in Derived class.

b. Protected members of Base class remain protected in Derived class.

c. Public members of Base class remain public in Derived class.

So, other classes can use public members of Base class through Derived class object.

2) Protected Inheritance:

a. Private members of Base class are not accessible in Derived class.

b. Protected members of Base class remain protected in Derived class.

c. Public members of Base class too become protected members of Derived class.

So, other classes can't use public members of Base class through Derived class object; but they are available to subclass of Derived.

3) Private Inheritance:

a. Private members of Base class are not accessible in Derived class.

b. Protected & public members of Base class become private members of Derived class.

So, no members of Base class can be accessed by other classes through Derived class object as they are private in Derived class. So, even subclass of Derived class can't access them.


Public inheritance models an IS-A relationship. With

class B {};
class D : public B {};

every D is a B.

Private inheritance models an IS-IMPLEMENTED-USING relationship (or whatever that's called). With

class B {};
class D : private B {};

a D is not a B, but every D uses its B in its implementation. Private inheritance can always be eliminated by using containment instead:

class B {};
class D {
  private: 
    B b_;
};

This D, too, can be implemented using B, in this case using its b_. Containment is a less tight coupling between types than inheritance, so in general it should be preferred. Sometimes using containment instead of private inheritance is not as convenient as private inheritance. Often that's a lame excuse for being lazy.

I don't think anyone knows what protected inheritance models. At least I haven't seen any convincing explanation yet.


If you inherit publicly from another class, everybody knows you are inheriting and you can be used polymorphically by anyone through a base class pointer.

If you inherit protectedly only your children classes will be able to use you polymorphically.

If you inherit privately only yourself will be able to execute parent class methods.

Which basically symbolizes the knowledge the rest of the classes have about your relationship with your parent class


Protected data members can be accessed by any classes that inherit from your class. Private data members, however, cannot. Let's say we have the following:

class MyClass {
    private:
        int myPrivateMember;    // lol
    protected:
        int myProtectedMember;
};

From within your extension to this class, referencing this.myPrivateMember won't work. However, this.myProtectedMember will. The value is still encapsulated, so if we have an instantiation of this class called myObj, then myObj.myProtectedMember won't work, so it is similar in function to a private data member.


Accessors    | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public       |      y     |       y       |   y
—————————————+————————————+———————————————+———————
protected    |      y     |       y       |   n
—————————————+————————————+———————————————+———————
private      |            |               |    
  or         |      y     |       n       |   n
no accessor  |            |               |

y: accessible
n: not accessible

Based on this example for java... I think a little table worth a thousand words :)


Summary:

  • Private: no one can see it except for within the class
  • Protected: Private + derived classes can see it
  • Public: the world can see it

When inheriting, you can (in some languages) change the protection type of a data member in certain direction, e.g. from protected to public.


Private:

The private members of a base class can only be accessed by members of that base class .

Public:

The public members of a base class can be accessed by members of that base class, members of its derived class as well as the members which are outside the base class and derived class.

Protected:

The protected members of a base class can be accessed by members of base class as well as members of its derived class.


In short:

private: base

protected: base + derived

public: base + derived + any other member


I found an easy answer and so thought of posting it for my future reference too.

링크 http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/에서

class Base
{
public:
    int m_nPublic; // can be accessed by anybody
private:
    int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
    int m_nProtected; // can be accessed by Base member functions, or derived classes.
};

class Derived: public Base
{
public:
    Derived()
    {
        // Derived's access to Base members is not influenced by the type of inheritance used,
        // so the following is always true:

        m_nPublic = 1; // allowed: can access public base members from derived class
        m_nPrivate = 2; // not allowed: can not access private base members from derived class
        m_nProtected = 3; // allowed: can access protected base members from derived class
    }
};

int main()
{
    Base cBase;
    cBase.m_nPublic = 1; // allowed: can access public members from outside class
    cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
    cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}

기본적으로 파생 클래스에있는 기본 클래스의 공용 및 보호 된 멤버에 대한 액세스 보호입니다. 공용 상속을 사용하면 파생 클래스가 기본의 공용 및 보호 된 멤버를 볼 수 있습니다. 개인 상속으로는 불가능합니다. protected를 사용하면 파생 클래스와이를 볼 수있는 파생 클래스가 있습니다.

참고 URL : https://stackoverflow.com/questions/860339/difference-between-private-public-and-protected-inheritance

반응형