다이아몬드 상속 (Diamond Polymorphism)
- 한 자식 클래스가 상속받는 서로 다른 부모 클래스들이, 같은 조부모 클래스를 상속받는 구조
예제
클래스
A
를B
,C
가 상속받은 후D
가B
와C
를 상속받으면,D::B::A
와D::C::A
가 각각 존재하게 된다.#include <iostream> class PoweredDevice { public: int i_; PoweredDevice(const int& power) { std::cout << "PoweredDevice: " << power << '\n'; } }; class Scanner : public PoweredDevice { public: Scanner(const int& scanner, const int& power) : PoweredDevice(power) { std::cout << "Scanner: " << scanner << '\n'; } }; class Printer : public PoweredDevice { public: Printer(const int& printer, const int& power) : PoweredDevice(power) { std::cout << "Printer: " << printer << '\n'; } }; class Copier : public Scanner, public Printer { public: Copier(const int& scanner, const int& printer, const int& power) : Scanner(scanner, power), Printer(printer, power) {} }; int main() { using namespace std; Copier cop(1, 2, 3); cout << &cop.Scanner::PoweredDevice::i_ << endl; cout << &cop.Printer::PoweredDevice::i_ << endl; } /* stdout PoweredDevice: 3 Scanner: 1 PoweredDevice: 3 Printer: 2 0000008F470FF798 0000008F470FF79C */
아래와 같이 상속 설정에서
virtual
키워드를 붙이면 해당 부모 클래스의 인스턴스가 하나만 사용된다.- 부모 클래스의 생성자를 따로 호출하지 않는 경우 에러가 발생했다.
#include <iostream> class PoweredDevice { public: int i_; PoweredDevice(const int& power) { std::cout << "PoweredDevice: " << power << '\n'; } }; class Scanner : virtual public PoweredDevice // 여기서 virtual 키워드 사용 { public: Scanner(const int& scanner, const int& power) : PoweredDevice(power) { std::cout << "Scanner: " << scanner << '\n'; } }; class Printer : virtual public PoweredDevice // 여기서 virtual 키워드 사용 { public: Printer(const int& printer, const int& power) : PoweredDevice(power) { std::cout << "Printer: " << printer << '\n'; } }; class Copier : public Scanner, public Printer { public: Copier(const int& scanner, const int& printer, const int& power) : Scanner(scanner, power), Printer(printer, power) // 에러 {} }; int main() { using namespace std; Copier cop(1, 2, 3); cout << &cop.Scanner::PoweredDevice::i_ << endl; cout << &cop.Printer::PoweredDevice::i_ << endl; }
error C2512: 'PoweredDevice::PoweredDevice': no appropriate default constructor available
- 부모 클래스(
PoweredDevice
)의 생성자를 명시하지 않으면 기본 생성자가 호출되는데, 현재 인자가 없는 생성자가 존재하지 않으므로 에러가 발생한 것이다.
에러가 나는 부분에 부모 클래스의 생성자를 호출하거나, 기본 생성자를 만들어주면 에러가 발생하지 않는다.
#include <iostream> class PoweredDevice { public: int i_; PoweredDevice(const int& power) { std::cout << "PoweredDevice: " << power << '\n'; } }; class Scanner : virtual public PoweredDevice { public: Scanner(const int& scanner, const int& power) : PoweredDevice(power) { std::cout << "Scanner: " << scanner << '\n'; } }; class Printer : virtual public PoweredDevice { public: Printer(const int& printer, const int& power) : PoweredDevice(power) { std::cout << "Printer: " << printer << '\n'; } }; class Copier : public Scanner, public Printer { public: Copier(const int& scanner, const int& printer, const int& power) : Scanner(scanner, power), Printer(printer, power), PoweredDevice(power) {} }; int main() { using namespace std; Copier cop(1, 2, 3); cout << &cop.Scanner::PoweredDevice::i_ << endl; cout << &cop.Printer::PoweredDevice::i_ << endl; } /* stdout PoweredDevice: 3 Scanner: 1 Printer: 2 00000094DE1BFA58 00000094DE1BFA58 */
- 아까와 달리
PoweredDevice: 3
이 한 번만 출력된 것을 볼 수 있고, 같은 메모리를 사용하는 것을 알 수 있다.
- 아까와 달리
'C++ > Class' 카테고리의 다른 글
C++ 동적 형변환 (Dynamic Casting) (0) | 2021.03.21 |
---|---|
C++ 객체 잘림 (Object Slicing) (0) | 2021.03.21 |
C++ 인터페이스 클래스 (Interface Class) (0) | 2021.03.21 |
C++ 추상 기본 클래스 (Abstract class) (0) | 2021.03.21 |
C++ 순수 가상 함수 (Pure Virtual Function) (0) | 2021.03.21 |