• 코드없는 프로그래밍 강의를 공부하고 정리한 내용입니다.

다중상속 예제

  • 먼저 상속처리한 클래스의 생성자가 먼저 호출된다


다중상속시 파생클래스의 크기는?

  • 포인터의 크기는 64비트에서는 8바이트, 32비트에서는 4바이트이다.
    => 위의 상황에서 LIger 클래스의 크기는
    Lion의 클래스 (8 + 8) + Tiger의 클래스 (8 + 8) + Liger(8)
    : 40바이트가 출력된다.

Lion *L = new Liger()를 할 경우, Lion클래스의 vTable만 Liger의 speak를 가리키게된다.

반대로
Tiger * L = new Liger()를 할 경우, Tiger클래스의 vTable만 Liger의 speak를 가리키게된다.

Liger * L = new Liger()를 할 경우에는, Tiger와 LIon 클래스 두개의 VTable이 모두 Liger의 speak를 가리키게 된다.

Diamond Inheritance

: Lion과 Tiger가 Animal 클래스를 상속받을 경우에 해당한다.
이때는 Animal클래스의 생성자가 2번 호출된다.
생성자 호출이 2번발생하는 것을 막기 위해서 virtual Inheritance를 이용하자

  • 소스코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Animal
{
public : 
	Animal()
	{
		cout << "Animal constructor" << endl;
	}

	virtual ~Animal()
	{
		cout << "Animal destructor " << endl;
	}

};

class Lion : public Animal
{
public : 
	Lion()
	{
		cout << "lion constructor" << endl;
	}

	virtual ~Lion()
	{
		cout << "lion destructor" << endl;
	}
	virtual void speak()
	{
		cout << "Lion! " << endl;
	}

private :
	double lionData;
};

class Tiger : public Animal
{
public:
	Tiger()
	{
		cout << "Tiger constructor" << endl;
	}

	virtual ~Tiger()
	{
		cout << "Tiger destructor" << endl;
	}

	virtual void speak()
	{
		cout << "Tiger! " << endl;
	}
private:
	double TigerData;
};

class Liger : public Lion, public Tiger
{
public:
	Liger()
	{
		cout << "Liger constructor" << endl;
	}

	~Liger()
	{
		cout << "Liger destructor" << endl;
	}

	void speak()
	{
		cout << "Liger! " << endl;
	}
private:
	double LigerData;
};

int main(void)
{
	Liger L;


}

-> virtual로 상속시키면 Animal의 생성자와 소멸자가 단 한번만 호출되는 것을 확인할 수 있다.

최종 소스코드

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Animal
{
public : 
	Animal()
	{
		cout << "Animal constructor" << endl;
	}

	virtual ~Animal()
	{
		cout << "Animal destructor " << endl;
	}

};

class Lion : virtual public Animal
{
public : 
	Lion()
	{
		cout << "lion constructor" << endl;
	}

	virtual ~Lion()
	{
		cout << "lion destructor" << endl;
	}
	virtual void speak()
	{
		cout << "Lion! " << endl;
	}

private :
	double lionData;
};

class Tiger : virtual public Animal
{
public:
	Tiger()
	{
		cout << "Tiger constructor" << endl;
	}

	virtual ~Tiger()
	{
		cout << "Tiger destructor" << endl;
	}

	virtual void speak()
	{
		cout << "Tiger! " << endl;
	}
private:
	double TigerData;
};

class Liger : public Lion, public Tiger
{
public:
	Liger()
	{
		cout << "Liger constructor" << endl;
	}

	~Liger()
	{
		cout << "Liger destructor" << endl;
	}

	//void speak()
	//{
//		cout << "Liger! " << endl;
	//}
private:
	double LigerData;
};

int main(void)
{
	Liger L;
	L.speak(); // 모호성을 발생함. 

}

=> Liger의 Speak함수를 재정의하면, 모호성 문제는 없어짐.

profile
🔥🔥🔥

0개의 댓글