득이공간
[Effective C++] 6장. 상속, 그리고 객체 지향 설계 본문
해당 게시물은 프로텍 미디어의 'Effective C++'를 읽고
학습한 내용을 개인적으로 요약한 글입니다.
📌 목차 - 6장. 상속, 그리고 객체 지향 설계
6-1. public 상속 모형은 반드시 “is-a”를 따르도록 만들자
6-2. 상속된 이름을 숨기는 일은 피하자
6-3. 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
6-4. 가상 함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자
6-5. 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물!
6-6. 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자
6-7. “has-a” 혹은 “is-implemented-in-terms-of”를 모형화할 때는 객체 합성을 사용하자
6-8. private 상속은 심사숙고해서 구사하자
6-9. 다중 상속은 심사숙고해서 사용하자
📌 6-1. public 상속 모형은 반드시 “is-a”를 따르도록 만들자
- public 상속의 의미는 “is-a”다. 기본 클래스에 적용되는 모든 것들이 파생 클래스에 그대로 적용되어야 한다. 왜냐하면 모든 파생 클래스 객체는 기본 클래스 객체의 일종이기 때문이다.
📌 6-2. 상속된 이름을 숨기는 일은 피하자
- 파생 클래스의 이름은 기본 클래스의 이름을 가린다. public 상속에서는 이런 이름 가림 현상이 바람직하지 않다.
- 가려진 이름을 다시 볼 수 있게 하는 방법으로, using 선언 혹은 전달 함수를 쓸 수 있다.
📌 6-3. 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
- 인터페이스 상속은 구현 상속과 다르다. public 상속에서, 파생 클래스는 항상 기본 클래스의 인터페이스를 모두 물려받는다.
- 순수 가상 함수는 인터페이스 상속만을 허용한다.
- 단순(비순수) 가상 함수는 인터페이스 상속과 더불어 기본 구현의 상속도 가능하도록 지정한다.
- 비가상 함수는 인터페이스 상속과 더불어 필수 구현의 상속도 가하도록 지정한다.
📌 6-4. 가상 함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자
- 가상 함수 대신에 쓸 수 있는 다른 방법으로 NVI 관용구 및 전략 패턴을 들 수 있다. 이 중 NVI 관용구는 그 자체가 템플릿 메서드 패턴의 한 예다.
- 객체에 필요한 기능을 멤버 함수로부터 클래스 외부의 비멤버 함수로 옮기면, 그 비멤버 함수는 그 클래스의 public 멤버가 아닌 것들을 접근할 수 없다는 단점이 생긴다.
- tr1::function 객체는 일반화된 함수 포인터처럼 동작한다. 이 객체는 주어진 대상 시그니처와 호환되는 모든 함수호출성 개체를 지원한다.
📌 6-5. 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물!
- 상속받은 비가상 함수를 재정의하는 일은 절대로 하지 말자.
📌 6-6. 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자
- 상속받은 기본 매개변수(초기화) 값은 절대로 재정의해서는 안 된다. 왜냐하면 기본 매개변수 값은 정적으로 바인딩되는 반면, 가상 함수(우리가 오버라이드할 수 있는 유일한 함수)는 동적으로 바인딩되기 때문이다.
📌 6-7. “has-a” 혹은 “is-implemented-in-terms-of”를 모형화할 때는 객체 합성을 사용하자
- 객체 합성(composition)의 의미는 public 상속이 가진 의미와 완전히 다르다.
- 응용 영역에서 객체 합성의 의미는 “has-a”다. 구현 영역에서는 “is-implemented-in-terms-of”의 의미를 갖는다.
📌 6-8. private 상속은 심사숙고해서 구사하자
- private 상속의 의미는 “is-implemented-in-terms-of”다. 대개 객체 합성과 비교해서 쓰이는 분야가 많지는 않지만, 파생 클래스 쪽에서 기본 클래스의 protected 멤버에 접근해야 할 경우 혹은 상속받은 가상 함수를 재정의해야 할 경우에는 private 상속이 나름대로 의미가 있다.
- 객체 합성과 달리, private 상속은 공백 기본 클래스 최적화(EBO)를 활성화시킬 수 있다. 이 점은 객체 크기를 가지고 고민하는 라이브러리 개발자에게 꽤 매력적인 특징이 되기도 한다.
📌 6-9. 다중 상속은 심사숙고해서 사용하자
- 다중 상속은 단일 상속보다 확실히 복잡하다. 새로운 모호성 문제를 일으킬 뿐만 아니라 가상 상속이 필요해질 수도 있다.
- 가상 상속을 쓰면 크기 비용, 속도 비용이 늘어나며, 초기화 및 대입 연산의 복잡도가 커진다. 따라서 가상 기본 클래스에는 데이터를 두지 않는 것이 현실적으로 가장 실용적이다.
- 다중 상속을 적법하게 쓸 수 있는 경우가 있다. 여러 시나리오 중 하나는, 인터페이스 클래스로부터 public 상속을 시킴과 동시에 구현을 돕는 클래스로부터 private 상속을 시키는 것이다.
'PS > C++' 카테고리의 다른 글
[Effective C++] 5장. 구현 (1) | 2025.03.18 |
---|---|
[Effective C++] 4장. 설계 및 선언 (0) | 2025.03.05 |
[Effective C++] 3장. 자원 관리 (0) | 2024.11.27 |
[Effective C++] 2장. 생성자, 소멸자 및 대입 연산자 (0) | 2024.11.02 |
[Effective C++] 1장. C++에 왔으면 C++의 법을 따릅시다 (1) | 2024.10.21 |