순수 가상 함수
virtual void speak() const = 0;
부모 클래스에서 자식 클래스에 특정 함수를 만들고 싶을 때 이것을 쓰는 것입니다.
그러면 만약에 speak()를 깜빡했을 때 오류가 뜨게 되는 것입니다. 이것이 바로 순수 가상 함수를 사용하는 이유입니다. 즉 자식 클래스가 깜빡할 경우를 대비해서 경고 표시를 만들어주는 것이라고 보면 됩니다.
class를 설계할 때 구조를 도와주는 것이라고 보면 됩니다.
다이아몬드 상속문제
#include <iostream>
#include <string>
using namespace std;
class PoweredDevice
{
public:
int m_i;
PoweredDevice(int power)
{
cout << "PowerDevice: " << power << '\n';
}
};
class Scanner : virtual public PoweredDevice
{
public:
Scanner(int scanner, int power)
: PoweredDevice(power)
{
cout << "Scanner : " << scanner << '\n';
}
};
class Printer : virtual public PoweredDevice
{
public:
Printer(int printer, int power)
: PoweredDevice(power)
{
cout << "Printer : " << printer << '\n';
}
};
class Copier : public Scanner, public Printer
{
public:
Copier(int scanner, int printer, int power)
: Scanner(scanner, power), Printer(printer, power),
PoweredDevice(power)
{
}
};
int main()
{
Copier cop(1, 2, 3);
cout << &cop.Scanner::PoweredDevice::m_i << endl;
cout << &cop.Printer::PoweredDevice::m_i << endl;
return 0;
}
전체코드입니다.
class PoweredDevice
{
public:
int m_i;
PoweredDevice(int power)
{
cout << "PowerDevice: " << power << '\n';
}
};
powerdevice 클래스는 m_i라는 멤버 변수를 가지고 있으며, 생성자에서 power값을 출력합니다.
class Scanner : virtual public PoweredDevice
{
public:
Scanner(int scanner, int power)
: PoweredDevice(power)
{
cout << "Scanner : " << scanner << '\n';
}
};
scanner 클래스는 powerdevice 를 가상 상속합니다. 생성자에서 poweredDevice의 생성자를 호출하고 scanner의 값을 출력합니다.
class Printer : virtual public PoweredDevice
{
public:
Printer(int printer, int power)
: PoweredDevice(power)
{
cout << "Printer : " << printer << '\n';
}
};
printer 클래스도 poweredDevice를 가상 상속합니다. 생성자에서 PoweredDevice의 생성자를호출하고 printer의 값을 출력합니다.
class Copier : public Scanner, public Printer
{
public:
Copier(int scanner, int printer, int power)
: Scanner(scanner, power), Printer(printer, power),
PoweredDevice(power)
{
}
};
Copier 클래스는 Scanner와 Printer를 다중 상속 받습니다. 생성자에서는 Scanner와 Printer의 생성자를 호출하고 PoweredDevice 생성자를 명시적으로 호출합니다. 가상 상속 덕분에 PoweredDevice의 생성자는 한 번만 호출됩니다.
int main()
{
Copier cop(1, 2, 3);
cout << &cop.Scanner::PoweredDevice::m_i << endl;
cout << &cop.Printer::PoweredDevice::m_i << endl;
return 0;
}
main 함수에서 Copier의 객체를 생성합니다. 이 과정에서 Scanner, Printer, 그리고 PoweredDevice의 생성자가 호출됩니다. PoweredDevice의 생성자는 가상 상속 덕분에 한 번만 호출됩니다.
PoweredDevice
/ \
Scanner Printer
\ /
Copier
다이아몬드 상속 구조는 현재 이런 식으로 되어 있습니다.
Scanner와 Printer가 각각 PoweredDevice를 상속받고, Copier가 이 둘을 상속받을 때, PoweredDevice의 인스턴스가 두 번 생성되는 문제가 발생할 수 있습니다.
이를 해결하기 위해 Scanner와 Printer는 PoweredDevice를 가상 상속합니다. 이렇게 하면 Copier가 생성될 대 PoweredDevice의 인스턴스는 한 번만 생성됩니다.
가상상속?
가상상속을 사용하면 최상위 클래스의 인스턴스가 중복 생성되지 않도록 보장합니다. Scanner와 Printer의 클래스에서 virtual키워드를 사용하여 PoweredDevice를 가상 상속하면, Copier클래스는 PoweredDevice의 인스턴스를 단 한 번만 생성성합니다.
'IT 프로그래밍 > C++' 카테고리의 다른 글
[C++] 가상 소멸자 (0) | 2024.05.28 |
---|---|
[c++] virtual 함수 (0) | 2024.05.28 |
[c++] 상속받은 함수를 오버라이딩 하기 (0) | 2024.05.27 |
[c++] 따배시 상속과 접근 지정자 (0) | 2024.05.27 |
[따배시 11.1 c++] 상속의 기본1 (0) | 2024.05.26 |