본문 바로가기
Object Oriented Programming(C++)/Effective C++

Effective C++ | 항목 39 private 상속은 심사숙고해서 구사하자

by continue96 2024. 8. 6.

 

Effective C++ 항목 39

 

항목 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)를 활성화할 수 있다.

 

댓글