죽음의 MI 마름모꼴(deadly MI diamond)라는 좋지 않은 모양이 나올 수도 있다. 하나의 기본 클래스에서 파생된 2개의 클래스가 있고 이 2개의 클레스를 하나의 클래스가 다중상속하는 경우를 말한다. 기본 클래스의 데이터 맴버가 경로 개수만큼 중복 생성되는 경우를 말하는 것인데, 진짜 알고도 이렇게 구현했어 ? 라는 의혹을 피해 가지 못한다.
class File {...}; class InputFile : public File { ... }; class OutputFile : public File { ... }; class IOFile : public InputFile, public OutputFile { ... };
만약 데이터 멤버의 중복생성을 원하는 것이 아니라면, 가상 상속을 사용해야 한다.
class File {...}; class InputFile : virtual public File { ... }; class OutputFile : virtual public File { ... }; class IOFile : public InputFile, public OutputFile { ... };
하지만 한가지만 명심히자. 가상 상속을 사용하는 클래스의 객체는 일반적으로 더 크다. 가상 기본 클래스의 데이터 맴버에 접근하는 속도도 더 느리다. 한마디로 가상 상속은 비싸다.
구태여 쓸 필요가 없다면 가상 상속은 쓰지말자. 가상 상속을 정말 쓰지 않으면 안 될 상황이라면, 가상 기본 클래스에 데이터를 넣지 않는 쪽으로 최대한 신경써라. (참고로 Java와 C#의 Interface는 데이터를 아에 갖지 못한다.)
다중 상속도 유용하게 쓰이는 경우가 있긴 있다.
Interface를 public으로 상속받아 구현하데, 거기에 필요한 구현들이 다른 클래스를 private로 상속받아서 쉽게 구현 될 경우가 그러하다.
class IPerson { // Interface Class public: virtual ~IPerson(); virtual std::string name() const = 0; virtual std::string birthDate() const = 0; }; class PersonInfo { // 구현을 도와줄수 있는 Class public: explicit Personinfo(DatabaseID pid); virtual ~PersonInfo(); virtual const char * theName() const; virtual char * theBirthDate() const; private: virtual const char* valueDelimOpen() const { return "["; } virtual const char* valueDelimClose() const { return "]"; } }; class CPerson : public IPerson, private PersonInfo { public: explicit CPerson(DatabaseID pid) : PersonInfo(pid) {} 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 ""; } };
* 다중 상속은 단일 상속보다 확실히 복잡합니다. 새로운 모호성 문제를 일으킬 뿐만 아니라 가상 상속이 필요해질 수도 있습니다.
* 가상 상속을 쓰면 크기 비용, 속도 비용이 늘어나며, 초기화 및 대입 연산의 복잡도가 커집니다. 따라서 가상 기본 클래스에는 데이터를 두지 않는 것이 현실적으로 가장 실용적입니다.
* 다중 상속을 적법하게 쓸 수 있는 경우가 있습니다. 여러 시나리오 중 하나는, 인터페이스 클래스로부터 public 상속을 시킴과 동시에 구현을 돕는 클래스로부터 private 상속을 시키는 것입니다.
댓글 없음:
댓글 쓰기