Chapter 11. 상속¶
'명품 C++Programming - 황기태' 8장 학습 내용
1절. 상속
2절. 파생 클래스
3절. 업 캐스팅과 다운 캐스팅
4절. 접근 상속 지정
5절. 생성자와 소멸자
6절. 다중 상속
7절. 가상 상속
1절. 상속¶
C++의 상속¶
- 클래스 사이에서 상속 관계 정의
- 객체 사이에는 상속 관계 없음
- 기본 클래스의 속성과 기능을 파생 클래스에 물려줌
- 기본 클래스(base class)
- 상속해주는 클래스
- 부모 클래스
- 파생 클래스(derived class)
- 상속받는 클래스
- 자식 클래스
- 기본 클래스의 속성과 기능을 물려받음
- 자신만의 속성과 기능을 추가하여 작성
- 기본 클래스에서 파생 클래스로 갈수록 클래스의 개념이 구체화
- 다중 상속을 통한 클래스의 재활용성 증가
상속의 표현¶
상속의 목적 및 장점¶
- 간결한 클래스 작성
- 기본 클래스의 기능을 물려받아 파생 클래스를 간결하게 작성
- 클래스 간의 계층적 분류 및 관리의 용이
- 상속은 클래스들의 구조적 관계 파악 용이
- 클래스 재사용과 확장을 통한 소프트웨어 생산성 향상
- 빠른 소프트웨어 생산 필요
- 기존에 작성한 클래스의 재사용 : 상속
- 상속받아 새로운 기능을 확장
- 앞으로 있을 상속에 대비한 클래스의 객체 지향적 설계 필요
상속 관계로 클래스의 간결화 사례 예시¶
상속 선언¶
- Student 클래스는 Person 클래스의 멤버를 물려받음
-
StudentWorker 클래스는 Student의 멤버를 물려받음
-
Student가 물려받은 Person의 멤버도 함께 물려받음
-
예제 1. Point 클래스를 상속받는 ColorPoint 클래스 예제
SourceCodeChecking
2절. 파생 클래스¶
파생 클래스의 객체 구성¶
파생 클래스에서 기본 클래스 멤버 접근¶
외부에서 파생 클래스 객체에 대한 접근¶
3절. 업 캐스팅과 다운 캐스팅¶
상속과 객체 포인터 : 업 캐스팅¶
- 업 캐스팅(up - casting)
- 파생 클래스 포인터가 기본 클래스 포인터에 치환
- ex) 사람을 동물로 보는 것(사람은 동물 안에 속함)
int main() {
ColorPoint cp;
ColorPoint *pDER = &cp;
Point* pBase = pDer;
// 업캐스팅
pDer->set(3, 4);
pBase->showPoint();
pDer->setColor("Red");
pDer->showColorPoint();
pBase->showColorPoint(); // 컴파일 오류
}
// 출력 예시
// (3, 4)
// Red(3, 4)
상속과 객체 포인터 : 다운 캐스팅¶
- 다운 캐스팅(down - casting)
- 기본 클래스의 포인터가 파생 클래스의 포인터에 치환되는 것
int main(){
ColorPoint cp;
ColorPoint *PDer;
Point* pBase = &cp;
// 업캐스팅
pBase->set(3, 4);
pBase->showPoint();
pDer = (ColorPoint *)pBase;
// 다운 캐스팅
// 강제 타입 변환이 반드시 필요
pDer->setColor("Red");
pDer->showColorPoint();
// 둘 다 정상 컴파일
}
// 출력 예시
// (3, 4)
// Red(3, 4)
4절. 접근 상속 지정¶
접근 지정자¶
- private 멤버
- 선언된 클래스 내에서만 접근 가능
- 파생 클래스에서도 기본 클래스의 private 멤버 직접 접근 불가
- public 멤버
- 선언된 클래스나 외부 어떤 클래스, 모든 외부 함수에 접근 허용
- 파생 클래스에서 기본 클래스의 public 멤버 접근 가능
- protected 멤버
- 선언된 클래스에서 접근 가능
- 파생된 클래스에서만 접근 허용
- 파생 클래스가 아닌 다른 클래스, 혹은 외부 함수에서는 protected 멤버 접근 불가
멤버의 접근 지정에 따른 접근성¶
- 예제 2. protected 멤버에 대한 접근 예제
SourceCodeChecking
상속 지정¶
- 상속 선언 시 public, private, protected의 3가지 중 하나 지정
- 기본 클래스 멤버의 접근 속성을 어떻게 계승할 것인지 지정
- public : 기본 클래스의 protected, public 멤버 속성을 그대로 계승
- private : 기본 클래스의 protected, public 멤버를 private로 계승
- protected : 기본 클래스의 protected, public 멤버를 protected로 계승
상속 시 접근 지정에 따른 멤버의 접근 지정 속성 변화¶
컴파일 오류 탐색 예제 3, 4, 5
-
예제 3. private 상속 사례 예제
SourceCodeChecking -
예제 4. protected 상속 사례 예제
SourceCodeChecking -
예제 5. 상속이 중첩될 때 접근 지정 사례 예제
SourceCodeChecking
5절. 생성자와 소멸자¶
상속 관계의 생성자와 소멸자¶
- 파생 클래스의 객체가 생성될 때
- 파생 클래스의 생성자와 기본 클래스의 생성자가 모두 실행
- 기본 클래스의 생성자가 먼저 실행된 후 파생 클래스의 생성자 실행
생성자 호출 관계 및 실행 순서¶
소멸자의 실행 순서¶
- 파생 클래스의 객체가 생성될 때
- 파생 클래스의 소멸자 먼저 실행
- 기본 클래스의 소멸자가 나중에 실행
컴파일러에 의해 묵시적으로 기본 클래스의 생성자를 선택하는 경우¶
- 파생 클래스의 생성자에서 기본 클래스의 기본 생성자 호출
기본 클래스에 기본 생성자가 없는 경우 : 컴파일 오류¶
매개 변수를 가진 파생 클래스의 생성자는 묵시적으로 기본 클래스의 기본 생성자 선택¶
- 파생 클래스의 매개 변수를 가진 생성자가 기본 클래스의 기본 생성자를 호출
파생 클래스의 생성자에서 명시적으로 기본 클래스의 생성자 선택¶
컴파일러의 기본 생성자 호출 코드 삽입¶
- 예제 6. TV, WideTV, SmartTV 생성자 매개 변수 전달 예제
SourceCodeChecking
6절. 다중 상속¶
기기의 컨버전스와 C++의 다중 상속¶
다중 상속 선언 및 멤버 호출¶
- 다중 상속 선언
class MP3{
public:
void play();
void stop();
};
class MobilePhone{
public:
bool sendCall();
bool receiveCall();
bool sendSMS();
bool receiveSMS();
};
class MusicPhone : public MP3, public MobilePhone{
// 다중 상속 선언
public:
void dial();
};
- 다중 상속 활용 1
void MusicPhone::dial(){
play(); // MP3 클래스의 play() 함수 호출
sendCall(); // MobilePhone 클래스의 sendCall() 함수 호출
}
- 다중 상속 활용 2
int main(){
MusicPhone hanPhone;
hanPhone.play(); // MP3 클래스의 play() 함수 호출
hanPhone.sendSMS(); // MobilePhone 클래스의 sendSMS() 함수 호출
}
- 예제 7. Adder와 Subtractor를 다중 상속받는 Calculator 클래스 작성 예제
SourceCodeChecking
다중 상속의 문제점¶
- 기본 클래스 멤버의 중복 상속
- 기본 클래스의 멤버가 이중으로 객체에 삽입되는 문제점
- 동일한 x를 접근하는 프로그램이 서로 다른 x에 접근하는 결과를 발생시킴
- 즉, 잘못된 실행 오류가 발생
7절. 가상 상속¶
가상 상속¶
- 다중 상속으로 인한 기본 클래스 멤버의 중복 상속 해결
- 가상 상속이란?
- 파생 클래스의 선언문에서 기본 클래스 앞에 virtual로 선언
- 파생 클래스의 객체가 생성될 때 기본 클래스의 멤버는 오직 한 번만 생성
- 기본 클래스의 멤버가 중복하여 생성되는 것을 방지
가상 상속의 해결법¶
- 가상 상속을 통해 다중 상속의 모호성 해결