개발/C++

가상 기초 클래스( virtual based class)

남생이야 2024. 6. 28. 01:12

 

가상 기초 클래스 

 

  C++은 클래스간의 다중 상속을 지원한다. 이는 한 클래스가 여러 부모의 기능들을 내포할 수 있단 의미가 되고 한 클래스로 여러 클래스 기능을 수행할 수 있어 얼핏 보면 대단해보이기도 한다. 

 

 그러나 다중 상속은 작업하는 데 있어서 부작용을 몇몇 일으킨다. 그 중에서 같은 부모를 상속 받은 파생클래스 두 가지를 또 상속 받는 파생클래스가 있다면 이 파생클래스로 객체지향의 특성 중 하나인 다형성을 이용해 기초 클래스로 마지막 파생 클래스를  사용할 땐 모호해지는 현상이 있다. (다이아몬드 상속) 

 

#include <iostream>

class Base {
public:
    virtual void show() {
        std::cout << "Base show" << std::endl;
    }
};

class Sub1 : public Base {
public:
    void show() override {
        std::cout << "Sub1 show" << std::endl;
    }
};

class Sub2 : public Base {
public:
    void show() override {
        std::cout << "Sub2 show" << std::endl;
    }
};

class Last : public Sub1, public Sub2 {
public:
///....
};

int main() {
    Last last;

    // Base 클래스 포인터로 Last 객체 참조시 모호한 참조가 된다. 
    Base* basePtr = &last;

  
    return 0;
}

 

   Last 클래스는 Sub1, Sub2를 상속 받는 클래스이다. 그리고 Sub1과 Sub2는 Base 클래스를 상속 받는 상태이다. Last 클래스 객체를 생성해서 이를 다형성의 성질로 Base 클래스로 참조하려 할 때, Sub1의 Base 인스턴스인지 Sub2의 인스턴스인지 모호해지기 때문에 관리하기 힘들다. 

 

 위와 같은 문제를 해결하기 위해 기초 클래스에 virtual 키워드를 붙여서 "가상 기초 클래스"를 생성하여 해결할 수 있다. 

 

#include <iostream>

class Base {
public:
    virtual void show() {
        std::cout << "Base show" << std::endl;
    }
};

class Sub1 : public virtual Base { 	// 접근 제한자와 virtual의 순서는 상관 없다.
public:
    void show() override {
        std::cout << "Sub1 show" << std::endl;
    }
};

class Sub2 : public virtual Base {
public:
    void show() override {
        std::cout << "Sub2 show" << std::endl;
    }
};

class Last : public Sub1, public Sub2 {
public:
    void show() override {
        // 모호성 해결: 하나의 Base 인스턴스만 존재
        Base::show();
    }
};

int main() {
    Last last;

    // Base 클래스 포인터로 Last 객체 참조
    Base* basePtr = &last;

    // 가상 상속으로 인해 모호성 없이 Base::show() 호출 가능
    basePtr->show();

    return 0;
}

 

 

  이를 해결하기 위해 Sub1, Sub2 클래스의 상속 키워드에 virtual 키워드를 추가한다면 Last 클래스에선 하나의 Base클래스만 상속하게 할 수 있다. 

 

가상 기초 클래스의 생성자 규칙

  가상 기초 클래스의 생성자 규칙은 특이한데 가상 기초 클래스의 생성자는 가장 나중에 파생된 클래스에서 호출된다. 이유는 다중 상속 구조에서 중복된 기초 클래스의 인스턴스 생성을 피하고 단일 인스턴스를 보장하기 위함이다.