C++ 다이아몬드 상속

Plato·2023년 5월 31일
0

서론

C++의 다이아몬드 상속은 C++를 다뤄본 학생/프로그래머라면 한 번쯤 경험하거나 들어봤을 개념이다. 하지만 가상 상속이 어떻게 다이아몬드 상속 문제를 해결하는지 오랫동안 와닿지 않았다. 이를 잘 설명하는 좋은 글을 발견해서 해당 내용을 소개하고자 한다.

본론

class A                     { public: void eat(){ cout<<"A";} }; 
class B: virtual public A   { public: void eat(){ cout<<"B";} }; 
class C: virtual public A   { public: void eat(){ cout<<"C";} }; 
class D: public         B,C { public: void eat(){ cout<<"D";} }; 

int main(){ 
    A *a = new D(); 
    a->eat(); 
} 

다이아몬드 상속에 대해 묻는 글에서 질문자는 위의 예시 코드를 제시하며 어떻게 가상 상속이 동작하는지 질문했다.
위의 코드에 대해 스택 오버플로의 유저 nnovich-OK는 아래와 같은 질문을 추가적으로 하며 답변을 시작한다.

  1. B와 C가 각각 다른 A 인스턴스를 생성하고자 하면 어떻게 동작하나? e.g. B와 C가 A의 다른 생성자를 사용해서 인스턴스를 생성한다면?
  2. B가 A를 그냥 상속받고 C가 A를 가상 상속 받는다면?
  3. 다이아몬드 상속 문제를 가상 상속이 풀어내니, 특별한 이유가 없다면 가상 상속을 사용하는게 맞나?

답변의 핵심은, class B: virtual A의 의미는 B를 상속받는 클래스가 A의 생성을 책임진다는 것이다.

그렇기에 위의 세 가지 질문에 대한 답은 아래와 같다.

  1. B와 C가 A의 어떤 생성자를 어떻게 호출하는지는 전혀 중요하지않다. D가 A의 어떤 생성자를 어떻게 호출하는지 결정한다. 그렇기에, D의 생성자에 특별한 내용이 없다면 A의 default 생성자를 통해 A의 인스턴스를 생성하고 A의 특정 생성자를 통해 A의 인스턴스를 생성하고 싶다면 D의 생성자에 해당 내용을 추가하면 된다.
  2. 이 경우, D와 B가 각각 A를 생성하기 때문에 다이아몬드 상속 문제는 해결되지 않는다.
  3. 자식이 아니라 손자가 base 클래스의 생성을 담당하는 건 좋은 패턴이 아니다. 꼭 필요한 경우에만 사용하는 것이 바람직하다.

참고문서

https://stackoverflow.com/questions/2659116/how-does-virtual-inheritance-solve-the-diamond-multiple-inheritance-ambiguit

0개의 댓글