[모던C++입문] 6.3 다중 상속

    6.3 다중 상속

    복수의 부모 클래스

    • 클래스는 여러 슈퍼 클래스에서 파생될 수 있다.
    class student
    {
        virtual void all_info() const 
        {   cout << "[student] My name is " << name << endl; }
        ...
    }
    
    class mathematician
    {
        virtual void all_info() const
        {   cout << "[mathman] My name is " << name << endl; }
        ...
    }
    
    class math_student : public student, public mathematician
    {
        //all_info를 정의하지 않으면 모호하게 상속된다
    }
    
    int main()
    {
        math_student bob("Robert Robson", "Algebra", "Fermat's Last Theorem");
        bob.all_info();
        //오류 : all_info 함수가 모호하다
    }

    공통의 조부모

    중복성과 모호함

    • 앞선 mathematician과 student에게 person이라는 슈퍼클래스를 추가해보자
    class person 
    {
        virtual void all_info() const 
        { cout << "[person]   My name is " << name << endl; }
        ...
    };
    
    class student : public person
    { ... }
    
    class mathematician : public person
    { 
        virtual void all_info() const 
        { 
            person::all_info();
        }
    }
    
    class math_student : public student, public mathematician
    {
        virtual void all_info() const override
        {
            student::all_info();
            mathematician::all_info();
        }
    }
    
    int main()
    {
        math_student bob("Robert Robson", "Algebra", "Fermat's Last Theorem");
        bob.all_info();
    
        //다음과 같이 출력된다
        //[student] My name is Rovert Robson
        //[person] My name is Rovert Robson
    }
    • 중복성 : 위의 코드는 person의 name을 두번 저장한다.
    • 오류 발생 쉬움 : name의 두 값이 일치 하지 않을 수 있음
    • 모호함 : math_student 에서 person::name에 접근할때 모호함

    가상 베이스 클래스

    • 가상 베이스 클래스(Virtual Base Class)를 사용하면 공통 슈퍼 클래스에 멤버를 한번만 저장한다.
    class person { ... };
    
    class student : public virtual person { ... };
    
    class mathematician : public virtual person { ... };
    
    class math_student : public student, public mathematician
    {
    public:
        math_student(const string& name, const string& passed, const string& proved) :
            student(name, passed), mathematician(name, proved) { }
        ...
    }
    
    int main()
    {
        math_student bob("Robert Robson", "Algebra", "Fermat's Last Theorem");
        bob.all_info();
    
        //다음과 같이 출력된다
        //[student] My name is 
        //  I passed the following grades: algebra
        //  I proved: Fermat's Last Theorem
    }
    • person 클래스의 생성자를 호출하는 동작은 가장 나중에 파생된 math_student 클래스에게 전가한다.
    • 그래서 mathematician과 student에서 person생성자를 호출하는 동작은 비활성화 된다
    • 따라서 person 생성자가 호출되지 않았고, name에 이름이 초기화 되지 못했다
    class student : public virtual person 
    {
        student(const string& passed) : passed(passed) { }
        ... 
    };
    
    class mathematician : public virtual person 
    {
        mathematician(const string& proved) : proved(proved) { }
        ... 
    };
    
    class math_student : public student, public mathematician
    {
    public:
        math_student(const string& name, const string& passed, const string& proved) :
            person(name), student(passed), mathematician(proved) { }
        ...
    }
    • 위와 같이 수정하여 person을 명시적으로 초기화해 name을 수정할 수 있게된다.
    반응형

    댓글

    Designed by JB FACTORY