일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 티스토리챌린지
- OpenAI
- Machine Learning
- 오블완
- ChatGPT
- gpt
- Classification
- deep learning
- supervised learning
- LLM
- PCA
- LG Aimers
- 지도학습
- 해커톤
- 회귀
- LG Aimers 4th
- 분류
- LG
- regression
- 머신러닝
- AI
- GPT-4
- 딥러닝
- Today
- Total
SYDev
C++ Chapter 09-2 : 다중상속(Multiple Inheritance)에 대한 이해 본문
다중상속은 논란이 많은 문법이지만, 예외적으로 혹은 매우 제한적으로 적용할 수도 있으므로 공부해보자.
다중상속은 다음 예제와 같이 간단하게 선언할 수 있다.
#include <iostream>
using namespace std;
class BaseOne
{
public:
void SimpleFuncOne() { cout<<"BaseOne"<<endl; }
};
class BaseTwo
{
public:
void SimpleFuncTwo() { cout<<"BaseTwo"<<endl; }
};
class MultiDerived : public BaseOne, protected BaseTwo
{
public:
void ComplexFunc()
{
SimpleFuncOne();
SimpleFuncTwo();
}
};
int main(void)
{
MultiDerived mdr;
mdr.ComplexFunc();
return 0;
}
BaseOne
BaseTwo
다중상속의 모호성(Ambiguous)
문제는 다중상속의 대상이 되는 두 개의 기초 클래스에 같은 이름의 함수가 있을 때 발생한다.
다음 예제를 통해 문제의 해결법을 간단히 살펴보자.
#include <iostream>
using namespace std;
class BaseOne
{
public:
void SimpleFunc() { cout<<"BaseOne"<<endl; }
};
class BaseTwo
{
public:
void SimpleFunc() { cout<<"BaseTwo"<<endl; }
};
class MultiDerived : public BaseOne, protected BaseTwo
{
public:
void ComplexFunc()
{
BaseOne::SimpleFunc();
BaseTwo::SimpleFunc();
}
};
int main(void)
{
MultiDerived mdr;
mdr.ComplexFunc();
return 0;
}
BaseOne
BaseTwo
가상 상속(Virtual Inheritance)
다중 상속의 모호성이 발생하는 다른 상황을 생각해보자. 클래스 Base를 두 개의 유도 클래스 MiddleDerivedOne, MiddleDerivedTwo 가 각각 상속한다고 가정해보자. 문제는 이 두 개의 유도 클래스를 다중 상속하는 클래스 LastDerived가 정의되면서 발생한다. 클래스 LastDerived는 Base를 상속하는 두 개의 클래스를 다중 상속하기 때문에 LastDerived 객체 내부에는 두 개의 Base 클래스 멤버가 존재한다. 따라서 이 경우에는 어느 클래스를 통해서 Base 클래스의 멤버함수를 호출할 것인지 명시해야 한다.
그런데 대부분의 상황에서 Base 클래스의 멤버가 LastDerived 객체 내부에 두 개씩 존재하는 것은 타당하지 않은 경우가 많기 때문에, Base 클래스를 딱 한 번만 상속하게 만들어야 한다. 이러한 상황에서 사용하는 것이 바로 가상 상속이다. 가상 상속 선언을 위해서는 상속 선언 앞에 키워드 virtual만 붙여주면 된다.
이러한 문제를 나타내는 다음 예제와 함께 살펴보자.
#include <iostream>
using namespace std;
class Base
{
public:
Base() {cout<<"Base Constructor"<<endl;}
void SimpleFunc() {cout<<"BaseOne"<<endl;}
};
class MiddleDerivedOne : virtual public Base //가상 상속 선언
{
public:
MiddleDerivedOne() : Base()
{
cout<<"MiddleDerivedOne Constructor"<<endl;
}
void MiddleFuncOne()
{
SimpleFunc();
cout<<"MiddleDerivedOne"<<endl;
}
};
class MiddleDerivedTwo : virtual public Base //가상 상속 선언
{
public:
MiddleDerivedTwo() : Base()
{
cout<<"MiddleDerived Constructor"<<endl;
}
void MiddleFuncTwo()
{
SimpleFunc();
cout<<"MiddleDerivedTwo"<<endl;
}
};
class LastDerived : public MiddleDerivedOne, public MiddleDerivedTwo
{
public:
LastDerived() : MiddleDerivedOne(), MiddleDerivedTwo()
{
cout<<"LastDerived Constructor"<<endl;
}
void ComplexFunc()
{
MiddleFuncOne();
MiddleFuncTwo();
SimpleFunc();
}
};
int main(void)
{
cout<<"객체생성 전 ..... "<<endl;
LastDerived ldr;
cout<<"객체생성 후 ..... "<<endl;
ldr.ComplexFunc();
return 0;
}
객체생성 전 .....
Base Constructor
MiddleDerivedOne Constructor
MiddleDerived Constructor
LastDerived Constructor
객체생성 후 .....
BaseOne
MiddleDerivedOne
BaseOne
MiddleDerivedTwo
BaseOne
위와 같이 다중상속하는 클래스 MiddleDerivedOne, MiddleDerivedTwo에 각각 가상 상속 선언을 함으로써, LastDerived의 객체 내부에는 Base 멤버가 하나씩만 존재하게 된다. 또한, 가상 상속으로 인 Base 클래스의 생성자가 한 번 만 호출되는 것을 확인할 수 있다.
출처 : 윤성우, <윤성우의 열혈 C++ 프로그래밍>, 오렌지미디어, 2010.05.12
'Programming Lang > C++' 카테고리의 다른 글
C++ Chapter 04-4 추가 내용 (0) | 2023.07.24 |
---|---|
C++ Chapter 10-1 : 연산자 오버로딩의 이해와 유형 (0) | 2023.07.23 |
C++ Chapter 09-1 : 멤버함수와 가상함수의 동작 원리 (0) | 2023.07.20 |
C++ Chapter 08-3 : 가상 소멸자와 참조자의 참조 가능성 (0) | 2023.07.19 |
C++ Chapter 08-2 : 가상함수(Virtual Function) (0) | 2023.07.19 |