항목 39 private 상속은 심사숙고해서 구사하자
39.1 public 상속 vs. private 상속
■ 39.1.1 public 상속과 private 상속의 차이점
- public 상속
- is-a 관계를 의미한다.
- 자식 클래스 타입이 부모 클래스 타입으로 암시적으로 변환된다.
- private 상속
- is-implemented-in-terms-of 관계를 의미한다. 즉, 소프트웨어 구현 영역으로서 의미만 있다.
- 자식 클래스 타입이 부모 클래스 타입으로 암시적으로 변환되지 않는다.
- 부모 클래스에 있는 접근 제한자가 private으로 변경된다.
39.2 private 상속 vs. 객체 합성
■ 39.2.1 private 상속과 객체 합성의 차이점
- is-implemented-in-terms-of를 구현할 때, 객체 합성을 사용한다.
- private 멤버에 접근할 때, 가상 함수를 재정의할 때만 private 상속을 사용한다.
class Timer
{
public:
explicit Timer(int _iFrequency);
virtual void OnTick() const;
};
// Timer 클래스를 private 상속해 객체 합성을 구현합니다.
class Widget : private Timer
{
private:
virtual void OnTick() const;
};
// WidgetTimer 클래스를 멤버 변수로 선언해 객체 합성을 구현합니다.
class Widget
{
private:
class WidgetTimer : public Timer
{
virtual void OnTick() const;
};
private:
WidgetTimer m_oWidgetTimer;
};
■ 39.2.2 객체 합성의 장점
- 객체 합성은 자식 클래스에서 부모 클래스의 가상 함수를 재정의할 수 없도록 설계할 수 있다.
- private 상속은 부모 클래스에 정의된 가상 함수를 호출할 수는 없어도 재정의할 수 있다.
- 객체 합성은 컴파일 의존성을 최소화한다.
- Timer 클래스를 private 상속하는 경우, Widget 클래스의 소스 코드에서 Timer 클래스의 헤더 파일을 포함(include)해야 한다.
- 객체를 합성하는 경우, WidgetTimer 클래스의 포인터만 선언하면 된다.
39.3 공백 기본 클래스 최적화
- 가상 함수, 비정적 데이터 멤버가 없는 클래스를 데이터가 없는 클래스, 즉 공백 클래스라고 한다.
- 독립 구조의 객체는 반드시 크기가 0을 넘어야 한다.
- 따라서 공백 클래스는 메모리를 차지하지 않을 것 같지만 1바이트(char) 크기를 갖는다.
- 자식 클래스 객체의 부모 클래스 부분은 위의 규칙을 따르지 않는다.
- Empty 객체는 기본 클래스로서 독립 구조 객체가 아니므로 0바이트를 차지한다.
- 이 기법을 공백 기본 클래스 최적화(empty base optimization, EBO)이라고 한다.
- 이 최적화 기법은 다중 상속일 때는 적용되지 않는다.
// 공백 클래스입니다.
class Empty {};
// HoldsAnInt 클래스는 8바이트를 차지합니다.
class HoldsAnInt
{
private:
int x;
Empty e;// 1바이트지만, 바이트 패딩으로 인해 4바이트를 차지합니다.
};
// HoldsAnInt 클래스는 4바이트를 차지합니다.
class HoldsAnInt : private Empty
{
private:
int x;
}
NOTE
① private 상속은 is implemented in terms of를 의미한다. 자식 클래스에서 부모 클래스의 protected 멤버에 접근할 때나 가상 함수를 재정의해야 할 때 의미가 있다.
② private 상속은 공백 기본 클래스 최적화(EBO)를 활성화할 수 있다.
'Object Oriented Programming(C++) > Effective C++' 카테고리의 다른 글
Effective C++ | 항목 41 템플릿 프로그래밍은 암시적 인터페이스와 컴파일 시간 다형성부터 (0) | 2024.08.06 |
---|---|
Effective C++ | 항목 40 다중 상속은 심사숙고해서 사용하자 (0) | 2024.08.06 |
Effective C++ | 항목 38 has-a 혹은 is-implemented-in-terms-of를 모형화할 때는 객체 합성을 사용하자 (0) | 2024.08.06 |
Effective C++ | 항목 37 어떤 함수에 대해서도 상속받은 디폴트 인수는 절대로 재정의하지 말자 (0) | 2024.07.26 |
Effective C++ | 항목 36 상속받은 비가상 함수를 자식 클래스에서 재정의하는 것은 절대 금물! (0) | 2023.05.21 |
댓글