본문 바로가기
  • 쓸쓸한 개발자의 공부방
C++

[C++] 다중 상속 (multiple inheritance)

by 심찬 2021. 12. 31.

 

 

다중 상속 (multiple inheritance)

 

다중 상속은 클래스가 2개 이상의 기반 클래스로 부터 상속 되는 것이다.

 - C++, Lisp, Curl 다중 상속 지원

 - Java, C# 다중 상속 미지원

 

문제점 : 서로 다른 기반 클래스에 동일 이름의 멤버가 있을 때 이름 충돌, 다이아몬드 형태의 상속

class InputFile
{
public:
    void read() {}
    void open() {}
};

class OutputFile
{
public:
    void write(){}
    void open() {}
};

class IOFile : public InputFile, public OutputFile // 다중 상속 지원
{    
};

int main()
{
    IOFile file;
    file.open(); // 동일 함수 존재로 인해 error
    
    file.InputFile::open();  // Right!
}

open()이 상속 받는 두 곳에 모두 존재하기 때문에 모호하여 에러 발생된다.

 

다이아몬드(Diamond) 상속 

 

아래 그림처럼 다이아몬드 형태의 상속 구조를 다이아몬드 상속이라 부른다.

아래와 같이 File을 상속 받는 InputFile과 OutputFile은 각각 File을 상속 받기 때문에 각각 File 클래스가 생성된다.

#include <iostream>
#include <string>

class File 
{
public:
    std::string filename;
    void open() {} // filename
};

class InputFile : public File 
{
public:
    void read() {}
};
class OutputFile : public File
{
public:
    void write(){}
    void open() {}
};
class IOFile : public InputFile, public OutputFile
{    
public:
};

int main()
{
    IOFile file;    
    file.open();
}

file.open()을 수행하면 아래와 같이 에러가 발생한다.

main.cpp:30:10: error: request for member ‘open’ is ambiguous
   30 |     file.open();
      |          ^~~~
main.cpp:8:10: note: candidates are: ‘void File::open()’
    8 |     void open() {} // filename
      |          ^~~~
main.cpp:20:10: note:                 ‘void OutputFile::open()’
   20 |     void open() {}
      |          ^~~~
main.cpp:8:10: note:                 ‘void File::open()’
    8 |     void open() {} // filename
      |          ^~~~

 

위 문제는 아래와 같은 방식으로 해결이 가능하다.

virtual 상속을 사용하면 File 인스턴스가 메모리에 한번만 생성되게 된다.

 

#include <iostream>
#include <string>

using namespace std;


class File 
{
public:
    std::string filename;
    void open() { cout << "File - open()";} // filename
};

class InputFile : virtual public File   // virtual 상속 사용
{
public:
    void read() {}
};
class OutputFile : virtual public File   // virtual 상속 사용
{
public:
    void write(){}
    void open( ) { cout << "OutputFile - open()";}
};
class IOFile : public InputFile, public OutputFile
{    
public:
};

int main()
{
    IOFile file;    
    file.open();
}

virtual 상속을 사용했기 때문에 아래와 같이 open()을 수행하면 OutputFile의 open()이 수행된다.

 

 

댓글