티스토리 뷰
6. 상속, 그리고 객체 지향 설계 (3)
항목 38 : "has-a(...는...를 가짐)" 혹은 "is-implemented-in-terms-of(...는...를 써서 구현됨)"를 모형화할 때는 객체 합성을 사용하자
합성(Composition)이란, 어떤 타입의 객체들이 그와 다른 타입의 객체들을 포함하고 있을 경우에 성립하는 그 타입들 사이의 관계를 일컫습니다.
응용 영역 : 객체 중 우리 일상생활에서 볼 수 있는 사물을 본 뜬 것들.
구현 영역 : 응용 영역에 속하지 않는 것들. 시스템 구현만을 위한 인공물.
연결 리스트를 재사용하는 Set 템플릿 예
// list를 잘못 사용한 예(is-a)
template<typename T>
class Set : public std::list<T> { ... };
list 객체는 중복 원소를 가질 수 있는 컨테이너이므로 Set 객체와 is-a 관계가 성립될 수 없습니다.
// list를 제대로 사용한 예(is implemented in terms of)
template<class T>
class Set
{
public:
bool member(cost T& item) const;
void insert(const T& item);
void remove(const T& item);
std::size_t size() const;
private:
std::list<T> rep;
};
- 객체 합성(composition)의 의미는 public 상속이 가진 의미와 완전히 다릅니다.
- 응용 영역에서 객체 합성의 의미는 has-a입니다. 구현 영역에서는 is-implemented-in-terms-of의 의미를 갖습니다.
항목 39 : private 상속은 심사숙고해서 구사하자
private 상속은 소프트웨어 설계(design) 도중에는 아무런 의미도 갖지 않으며, 단지 소프트웨어 구현(implementation) 중에만 의미를 가질 뿐입니다.
할 수 있으면 객체 합성을 사용하고, 꼭 해야 하면 private 상속을 사용하십시오.
타이머를 사용하는 Widget 객체 예
class Timer
{
public:
explicit Timer(int tickFrequency);
// 일정 시간이 경과할 때마다 자동으로 호출
virtual void onTick() const;
};
// 항목 18("제대로 사용하기에는 쉽게, 잘못 사용하기에는 어렵게 만들라") 위반
class Widget: private Timer
{
private:
// Widget 사용 자료 등을 수집
virtual void onTick() const;
...
};
올바른 예 - public 상속에 객체 합성 조합
class Widget
{
private:
class WidgetTimer: public Timer
{
public:
virtual void onTick() const;
...
};
WidgetTimer timer;
...
};
public 상속에 객체 합성 조합의 이점
1. 파생은 가능하게 하되, 파생 클래스에서 onTick을 재정의할 수 없도록 설계 가능.
2. Widget의 컴파일 의존성을 최소화.
- private 상속의 의미는 is-implemented-in-terms-of입니다. 대개 객체 합성과 비교해서 쓰이는 분야가 많지는 않지만, 파생 클래스 쪽에서 기본 클래스의 protected 멤버에 접근해야 할 경우 혹은 상속받은 가상 함수를 재정의해야 할 경우에는 private 상속이 나름대로 의미가 있습니다.
- 객체 합성과 달리, private 상속은 공백 기본 클래스 최적화(EBO)를 활성화시킬 수 있습니다. 이 점은 객체 크기를 가지고 고민하는 라이브러리 개발자에게 꽤 매력적인 특징이 되기도 합니다.
항목 40 : 다중 상속은 심사숙고해서 사용하자
다중 상속을 올바르게 사용한 예 - 인터페이스의 public 상속과 구현의 private 상속의 조합
// 용도에 따라 구현될 인터페이스
class IPerson
{
public:
virtual ~IPerson();
virtual std::string name() const = 0;
virtual std::string birthDate() const = 0;
};
class DatabaseID { ... };
// IPerson 인터페이스를 구현하는데 유용한 함수 포함
class PersonInfo
{
public:
explicit PersonInfo(DatabaseID pid);
virtual ~Person();
virtual const char *theName() const;
virtual const char *theBirthDate() const;
virtual const char *valueDelimOpen() const;
virtual const char *valueDelimClose() const;
...
};
class CPerson: public IPerson, private PersonInfo
{
public:
explicit CPerson(DatabaseID pid) : PersonInfo(pid) {}
// IPerson 클래스의 순수 가상 함수에 대해 파생 클래스의 구현 제공
virtual std::string name() const
{ return PersonInfo::theName(); }
virtual std::string birthDate() const
{ return PersonInfo::theBirthDate(); }
private:
// 구분자에 관련된 가상 함수들도 상속되므로 이 함수들에 대한 재정의 버전을 만듭니다.
const char *valueDelimOpen() const { return " "; }
const char *valueDelimClose() const { return " "; }
};
// 유일한 데이터베이스 ID로부터 IPerson 객체를 만들어내는 팩토리 함수
std::tr1::shared_ptr<IPerson> makePerson(DatabaseID personIdentifier);
// 사용자로부터 데이터베이스 ID를 얻어내는 함수
DatabaseID askUserForDatabaseID();
DatabaseID id(askUserForDatabaseID());
std::tr1::shared_ptr<IPerson> pp(makePerson(id));
// IPerson 인터페이스를 지원하는 객체를 하나 만들고 pp로 가리키게 합니다.
// 이후에는 *pp의 조작을 위해 IPerson의 멤버 함수를 사용합니다.
...
- 다중 상속은 단일 상속보다 확실히 복잡합니다. 새로운 모호성 문제를 일으킬 뿐만 아니라 가상 상속이 필요해질 수도 있습니다.
- 가상 상속을 쓰면 크기 비용, 속도 비용이 늘어나며, 초기화 몇 대입 연산의 복잡도가 커집니다. 따라서 가상 기본 클래스에는 데이터를 두지 않을 것이 현실적으로 가장 실용적입니다.
- 다중 상속을 적법하게 쓸 수 있는 경우가 있습니다. 여러 시나리오 중 하나는, 인터페이스 클래스로부터 public 상속을 시킴과 동시에 구현을 돕는 클래스로부터 private 상속을 시키는 것입니다.
- James Song
'Books_tech' 카테고리의 다른 글
다시 읽는 <Effective C++> Chapter 7 요약 (2) (0) | 2015.12.19 |
---|---|
다시 읽는 <Effective C++> Chapter 7 요약 (1) (0) | 2015.12.09 |
다시 읽는 <Effective C++> Chapter 6 요약 (2) (0) | 2015.11.24 |
다시 읽는 <Effective C++> Chapter 6 요약 (1) (0) | 2015.11.20 |
다시 읽는 <Effective C++> Chapter 5 요약 (2) (0) | 2015.11.12 |
- #build2016
- #cplusplus
- #프로그래밍심리학
- #클린코드
- #techdays2015
- #팀개발
- #제럴드와인버그
- #로버트마틴
- #임백준
- 상속
- #EffectiveModernCpp
- #레거시코드
- #cpp
- #마이클페더스
- #mva
- #scottmeyers
- #csharp
- #자녀교육
- #ModernCPP
- #세미나
- #알고리즘
- Effective C++
- #스콧마이어스
- #코드최적화
- #ndc
- 객체 지향 설계
- #uwp
- Effective Modern C++
- Scott Meyers
- 책
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |