[C++] 상속 기본

강민석·2022년 10월 18일
0

이것이 C++이다

목록 보기
5/8
post-thumbnail

6.1 상속이란?

6.1.1 기본 문법

  • 클래스를 선언할 때, 특정 클래스를 상속받으려면 다음과 같이 코드를 작성한다.
class 파생클래스명: 접근제어지시자 부모클래스명

// 기본 클래스 혹은 부모 클래스
class CMyData {

};

// 파생 클래스 혹은 자식 클래스
class CMyDataEx: public CMyData {

};
  • 파생 클래스의 인스턴스가 생성될 때 기본 클래스의 생성자도 호출된다.

  • 파생 클래스는 기본 클래스의 멤버에 접근할 수 있다. (private 제외)

  • 파생 클래스의 인스턴스를 통해 기본 클래스 메서드를 호출할 수 있다.

  • 상속 관계에서 파생 클래스의 생성자는 먼저 호출되지만 실행은 나중에 된다.

    1. 파생 클래스 인스턴스 생성
    2. 상위 클래스 생성자 호출
    3. 상위 클래스 생성자 실행 및 반환
    4. 파생 클래스 생성자 실행
    5. 파생 클래스 생성자 반환

  • private으로 선언된 멤버는 파생 클래스에서 접근이 불가능하다.
  • protected으로 선언된 멤버는 파생 클래스에서만 접근이 가능하며, 외부에서는 접근이 불가능하다.

6.2 메서드 재정의 (Override)

  • 파생 클래스에서 기본 클래스의 메서드를 재정의하면 기존의 것은 무시되고 새로 정의된 것이 기존 것을 대체한다.

6.2.1 기본 문법 및 특징

  • 파생 형식에서 기본 형식의 동일한 메서드를 호출하려면 반드시 소속 클래스를 명시해야 한다.
    • 그렇지 않으면 재귀호출이 되어버림.
  • 메서드의 재정의는 기존의 코드를 제거하기 위해서라기보단, 기존 메서드에 부가적인 기능을 추가하는데에 의의가 있다.
  • 명시적 호출(b.CMyData::SetData(15))을 통해 직접 상위 기본 클래스의 메서드를 호출할 수 있다.

6.2.2 참조 형식과 실 형식

  • 다음과 같이 파생 형식기본 형식으로 참조할 수 있다.
int main(int argc, char* argv[]) {
    CMyDataEx a;
    CMyData &rData = a; // 참조자를 이용한 참조
    CMyData *pData = new CMyDataEx; // 포인터를 이용한 참조

    rData.SetData(15);
    pData->SetData(11);

    cout << rData.GetData() << endl;

    delete pData;

    return 0;
}
  • 참조 형식과 실 형식이 다른 경우, 묵시적인 호출로 참조 형식의 메서드가 호출된다.
  • 즉, 위 코드의 6, 7번 줄에서 CMyDataEx::SetData가 아닌 CMyData::SetData가 호출된다.
  • 위 코드에서 pDatadelete 하더라도 CMyDataEx의 소멸자가 호출되지 않으므로, 메모리 누수 문제가 발생한다.
    • '7.1.3 소멸자 가상화'에서 다룸.

6.3 상속에서의 생성자와 소멸자

  • 클래스 A, B, C에 대하여 AB의 기본이고 BC의 기본 클래스인 상속 관계라 하자.
  • 세 클래스의 생성자와 소멸자의 관계는 다음과 같다.
    • C 클래스의 인스턴스를 선언하면 생성자의 호출 순서C, B, A이다.
    • 생성자의 실행 순서는 이의 역순인 A, B, C이다.
    • C 클래스의 인스턴스가 소멸하면 소멸자가 A, B, C 순서대로 호출 및 실행된다.
    • 즉, 상속 관계에 있는 클래스들의 생성자는 호출 순서와 실행 순서가 반대고, 소멸자는 동일하다.

6.3.1 호출 순서

  • 가령, 파생 클래스의 소멸자에서 부모 클래스의 포인터 변수의 메모리를 미리 해제하는 경우 소멸자의 호출 순서에 의해 심각한 오류가 발생할 수 있다.
    • 이와같은 상황을 피하기 위해선 파생 클래스에서 부모 클래스의 멤버 변수에 직접 쓰기 연산을 하지 않아야 한다.
    • 또한 파생 클래스 생성자에서 부모 클래스 멤버 변수를 초기화 해서도 안된다.
    • 생성자와 소멸자는 객체 자신의 초기화 및 해제만 생각하자.

6.3.2 생성자 선택

  • 파생 클래스의 생성자는 기본 클래스의 생성자 중 어떤 것이 호출될 것인지 선택할 수 있다. -> '생성자 초기화 목록'과 같은 방식으로 기술
  • C++11부터 추가된 '생성자 상속' 기능을 통해 파생 클래스에서 기본 클래스에 다중 정의된 생성자들을 그대로 가져올 수 있다.
class CMyDataEx: public CMyData {
public:
    using CMyData::CMyData;
}

0개의 댓글