base클래스가 1개만 있는 경우 선형(linear)적인 상속이라고 한다

(아래에서 위로 올라가면 하나밖에없다)

이렇게 여러 개의 base 클래스를 갖는 경우를 다중상속이라 한다.
#include <iostream>
class Animal
{
public:
Animal(){
std::cout << "Animal constructor" << std::endl;
}
virtual void speak()
{
std::cout << "Animal!" << std::endl;
}
virtual ~Animal(){
std::cout << "Animal destructor" << std::endl;
}
private:
double animalData;
};
class Lion : virtual public Animal
{
public:
Lion(){
std::cout << "Lion constructor" << std::endl;
}
virtual void speak()
{
std::cout << "Lion!" << std::endl;
}
virtual ~Lion(){
std::cout << "Lion destructor" << std::endl;
}
private:
double lionData;
};
class Tiger : virtual public Animal
{
public:
Tiger(){
std::cout << "Tiger constructor" << std::endl;
}
virtual void speak()
{
std::cout << "Tiger!" << std::endl;
}
virtual ~Tiger(){
std::cout << "Tiger destructor" << std::endl;
}
private:
double tigerData;
};
class Liger : public Tiger, public Lion
{
public:
Liger(){
std::cout << "Liger constructor" << std::endl;
}
void speak() override
{
std::cout << "Liger!" << std::endl;
}
~Liger(){
std::cout << "Liger destructor" << std::endl;
}
private:
double ligerData;
};
int main()
{
Liger liger;
return 0;
}
여기서 class Liger : public Lion, public Tiger
Lion과 Tiger의 순서에 따라 생성자와 소멸자가 불러와지는 순서가 달라진다.


그리고 liger.speak();를 실행해보면

liger의 크기를 보면 40bytes가 나오는데

64bits컴퓨터이므로 포인터는 8bytes,
lion과 tiger과 liger의 double 변수 8bytes이므로 총 40bytes가 나온다.
Lion포인터를 이용해 Lion * polyLion = new Liger();를 생성하고
polyLion->speak();
delete polyLion;을 실행하면 Liger를 출력하는데
new Liger()로 liger 객체를 만들지만 Lion 포인터로 인해 빨간색으로 칠한 Lion 객체 부분만 볼 수 있고
가상테이블 주소를 저장하는 포인터가 speak()함수를 가지고 있는 Liger 가상테이블을 가리키기 때문이다.
만약 Liger * polyLion = new Liger(); Liger포인터에 Liger를 할당하면
Liger포인터는 객체 전부를 볼 수 있다

이 때 Lion, Tiger객체의 포인터는 모두 Liger 가상테이블을 가리킨다.