본문 바로가기
책 정리/Effective C++ 3rd

항목 39. private 상속은 심사숙고해서 구사하자

by ocean20 2020. 3. 16.

public 상속(is- a 관계)이 아닌 private 상속을 살펴보자.

class Person {…};
class Student : private Person { … };  //private 상속
void eat(const Person& p);  // 사람이든 학생이든 먹을 수 있다.
void study(const Student& s); // 공부는 학생만할 수 있다.
Person p;  
Student s; 
eat(p);   // OK ! p는 Person의 일종이다.
eat(s);   // Error! Student는 Person의 일종이 아니다.(public 상속이 아니기 때문에)

 

1. private 상속의 특징

  1) 파생클래스 객체(Student)에서 기본클래스 객체(Person) 변환하지 않는다.

  * 기본클래스의 접근영역이 protected, public이었음에도 불구하고(, protected, public -> private 한다.)

 

  2) private 상속의 의미는 , is-implemented-in-terms-of처럼 구현기법중 하나다.

  * private is-imple.. 포함관계라고 생각하면 되겠다.

 

  Q. 객체합성도 private상속과 같이 is-imple.. 뜻을 가진다고 하였다. 그럼 2가지 어떤 사용해야할까?

  A. 있으면 객체 합성을 사용하고, 해야 한다면 private 상속을 쓰자.

( * private 상속은 다른 클래스의 비공개 멤버 접근이 필요하거나, 가상함수를 재정의할때 쓴다. )

 


2. private 상속 VS 객체합성

  1) 기본 클래스 Timer

class Timer {
public :
  explicit Time(int tickFrequency);
  virtual void onTick() const;  // 일정 시간 초과시 이함수가 호출된다.
};

 

자, 이제 Timer onTick() 을 다른클래스에서 사용해보고 싶다. ( is-imple… 구현기법)

 

  2) private 상속으로 풀어가보자.

class Widget : private Timer{
private:
  virtual void onTick() const;
  …
};

  * 풀이 : Timer 가상함수를 Widget 클래스에서 재정의가 필요하므로 상속을 받았다.

Widget Timer is-a 관계가 아니므로 private 상속을 구현하였다.

또한, Widget객체의 사용자는 Widget객체를 통해 onTick함수를 호출해선 안된다.

함수는 개념적으로 Widget 인터페이스로 없기 때문이다.

항목 18. (제대로 사용하기쉽게…) 다시 확인해보자. onTick public 빼놓는순간 항목18. 위반이다.

 

  3) 객체합성으로 풀어가보자.

class Widget{
private :
  class WidgetTimer : public timer{
  public :
    virtual void onTick() const;
    …
  };
  WidgetTimer timer;
  …
};

  * 풀이 : 상당히 복잡한 구조다. public 상속 + 객체 합성

 

장점1. Widget클래스를 파생 가능하게 하되, onTick() 재정의 없도록 막아 두었다. private상속으로 구현했다면, 가상함수를 호출 없으나, 재정의는 가능했을 것이다.

 

장점2. 컴파일 의존성을 최소화 있다. WidgetTimer 정의를 Wiget으로 부터 빼내고 Widget WigetTimer객체에 대한 포인터만 빼두면 #include 없이 사용가능하다.


3. 결론

* private 상속이 최선인 경우는 아무리 주어도 is-a관계로 이어질 같지 않을 클래스를 사용해야하는데, 한쪽이 다른쪽 클래스의 protected 또는 private 접근이 필요할때, 또는 다른쪽클래스의 가상함수를 재정의해야할때이다.

 

설계가 필요할 private 상속은 가장 마지막 우선순위로 두고, 다른방법을 먼저 생각해보자.(ex. 객체합성 + public 상속)

 


이것만은 잊지 말자!

-  private 상속의 의미는 is-implemented-in-terms-of 이다. 객체합성에 비해 쓰이는 경우가 많지 않다. 하지만, is-a 관계가 아닌 다른클래스의 가상함수를 재정의할때, 비공개영역을 접근해야할때 private 상속을 사용한다.

- 객체 합성과 달리 private 상속은 기본클래스 최적화(EBO) 활성화 시킬 있다. 점은 객체 크기를 가지고 고민하는 개발자에게 매력적이다. (내용 pass 하였다...2020.03.16)

댓글