티스토리 뷰

목차

    C++ 상속, 다이아몬드 문제란? 그리고 피하는 방법


    C++ 상속, 다이아몬드 문제란[C++ 다중상속] Diamond problem


    위 그림은 C++ 상속, 다이아몬드 문제를 이해하는 데 도움이 됩니다.


    클래스 A에서 파생되는 클래스 B와 C가 있다고 가정합니다. 그리고 C++ 상속(다이아몬드를 유발하는 다중 상속)으로 클래스 B와 C의 파생 클래스 D도 생성합니다. (상상만으로도 한숨 나오는 C++ 상속 구조입니다)


    여기서 C++ 상속, 다이아몬드 문제의 발생 이유가 나타납니다. 위 그림을 토대로 구체적인 코드를 작성해 보겠습니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    --
    Animal 클래스는 윗 그림의 클래스 D와 같습니다.
    --
                        
    class Animal { -- ... -- }; // base class
    {
        int weight;
     
        public:
            int getWeight() { return weight;};
    };
     
    class Tiger : public Animal { -- ... -- };
    class Lion : public Animal { -- ... -- }    
    class Liger : public Tiger, public Lion { -- ... -- };
    cs


    위의 코드가 C++ 상속, 다이아몬드 문제를 유발하는 실제 예시입니다.


    Animal 클래스는 최상위 클래스 A와 같으며, Tiger와 Lion은 클래스 B와 C, Liger 클래스는 D 클래스에 해당합니다.


    위와 같은 다중 상속으로 생기는 문제점이 무엇인지는 아래 코드에서 나타납니다.


    1
    2
    3
    4
    5
    6
    int main( )
    {
        Liger lg ;
        --COMPILE ERROR--
        int weight = lg.getWeight();
    }
    cs


    C++ 상속되는 계층 구조에서 Tiger와 Lion 클래스 모두 Animal이란 기본 클래스에서 파생되는 것이 확인되죠.


    C++ 상속 문제[C++ 다중상속] Diamond problem


    C++ 상속, 다이아몬드 문제가 여기에 있습니다.


    Liger 클래스에서 Tiger, Lion 클래스가 파생됨.

    두 클래스 모두 Animal 클래스의 멤버 데이터와 함수를 갖게 됩니다.

    Liger 객체 "lg"는 Animal을 상속받는 두 개의 클래스 모두가 보유하게 됩니다.


    Liger의 객체를 보유한 2개의 서브 클래스가 "lg.getWeight()"로 호출했을 때 어떤 컴파일 에러가 발생할까요?


    컴파일러는 getWeight를 호출하는 Liger 클래스의 객체 lg의 정확한 C++ 상속 관계를 알 수 없습니다.


    그래서 위의 코드에선 getWeight에 대한 호출이 "모호(ambiguous)"해서 컴파일러는 정상적으로 수행되지 못합니다.


    다이아몬드 문제(Diamond Problem) 해결책

    위에서 C++ 상속, 다이아몬드 문제 원인을 살펴봤습니다.


    이 문제를 해결할 방법은 Virtual 키워드 사용입니다. 상속 관계에서 Virtual 키워드를 사용한다면, Liger의 객체가 서브 클래스 모두에 생성되는 것을 방지할 수 있습니다.


    아래는 그 예입니다.


    1
    2
    class Tiger : virtual public Animal { -- ... -- };
    class Lion : virtual public Animal { -- ... -- };
    cs


    간단하게, Tiger와 Lion 클래스 선언 시 "Virtual" 키워드를 추가해줍니다.


    1
    2
    3
    4
    5
    int main( )
    {
        Liger lg;
        int weight = lg.getWeight();
    }
    cs


    이렇게 C++ 상속, 다이아몬드 문제를 살펴봤습니다.


    C++ 상속 다이아몬드 문제 방법[C++ 다중상속] Diamond problem


    다이아몬드 상속 문제에 대해선 이거 하나만 딱 기억하세요.


    쓰면 안 된다. 쓰지 마.


    가끔 쓸 때는 써야 한다는 이야기도 있는데, 제 생각엔 쓸 때가 없습니다. 쓰지 않고도 구현할 방법은 있으니깐요.


    C++ 상속, 다이아몬드 문제란? 그리고 피하는 방법