차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

상속 [2015/01/10 11:24] (현재)
raychani 만듦
줄 1: 줄 1:
 +====== 상속 ======
 +**상속**은 누군가에게 무언가를 물려받는 것을 말한다. 물론 이 블로그에선 객체지향 프로그래밍에서 얘기하는 상속을 다룬다.
 +
 +다른 언어도 그렇지만 c++에서 상속은 꽤나 복잡한 문제이다. 생성자와 소멸자가 특히 문제를 복잡하게 한다. 이 페이지에서는 c++ 상속관계에서 생성자와 소멸자 호출 문제를 설명한다.
 +
 +{{tag>​cpp code oop}}
 +
 +다음과 같은 클래스가 있다.
 +
 +<​code>​
 +class IMyClass // 단순한 인터페이스 클래스
 +{
 +public:
 +  virtual void Print() = 0; // 단순한 인터페이스 하나 선언
 +};
 +
 +class CMyClass : public IMyClass ​
 +{
 +IMyClass* m_pNext;
 +public:
 +  CMyClass() {cout << "​CMyClass Constructor"​ << endl;} // 생성자가 불리는지 확인
 +  ~CMyClass() {cout << "​CMyClass Destructor"​ << endl;} // 소멸자가 불리는지 확인
 +  void Print() {cout << "​CMyClass"​ << endl;} // IMyClass의 인터페이스 구현
 +};
 +</​code>​
 +
 +이 클래스를 다음과 같이 생성, 사용, 삭제하였을 때 생성자, 소멸자는 어떻게 호출될까?​
 +
 +<​code>​
 +IMyClass *pMyClass = new CMyClass;
 +pMyClass->​Print();​
 +delete pMyClass
 +</​code>​
 +
 +첫줄에서 CMyClass의 객체를 실제 만들었으므로 CMyClass의 생성자가 호출된다.
 +
 +두번째 줄에서 pMyClass는 IMyClass의 변수이나 virtual로 선언된 멤버 함수를 호출하기 때문에, 실제 객체인 CMyClass에서 구현한 Print가 호출된다.
 +
 +세번째 줄이 문제이다. pMyClass의 실제 객체는 CMyClass지만 CMyClass의 소멸자는 ~CMyClass이고 IMyClass의 소멸자는 ~IMyClass이다. 포인터가 IMyClass이기 때문에 C++ 컴파일러 내부에서 자동으로 생성한 기본 소멸자인 ~IMyClass()만 호출하고 종료된다. 만약 CMyClass의 소멸자에서 메모리 해제 등의 일을 구현한 경우 이것은 무시당한다. 올바른 IMyClass 코드는 다음과 같다.
 +
 +<​code>​
 +class IMyClass // 단순한 인터페이스 클래스
 +{
 +public:
 +  IMyClass() {}; // 생성자는 그냥 추가해도 된다.
 +  virtual ~IMyClass() {}; // 소멸자는 반드시 virtual 키워드가 필요하다.
 +  virtual void Print() = 0; // 단순한 인터페이스 하나 선언
 +};
 +</​code>​
 +
 +생성자의 경우는 객체 생성 시 필요한 생성자를 정확히 호출하므로 별 문제가 되지 않는다. 그러나 소멸자의 경우는 어느 포인터를 사용하여 소멸자를 호출할 지 알 수 없으므로 위와 같이 가상함수로 소멸자를 정의하여야 한다. 물론 ~IMyClass의 가상함수를 정의했다고 하여, CMyClass에서도 ~IMyClass()를 오버라이드할 필요는 없다. CMyClass에서는 ~CMyClass()를 구현하면,​ IMyClass의 소멸자가 호출되는 경우 자동으로 CMyClass의 소멸자가 불리게 된다.
 +