1. 상속
1) 컨트롤 클래스 / 핸들러 클래스란?
- 프로그램에서 기능 처리의 실제 주체 역할을 수행하는 클래스를
컨트롤 클래스(Control Class) 또는 핸들러 클래스(Handler Class)라고 부른다.
✅ 이 클래스는 보통 기타 클래스들의 객체를 생성하고 조작하며,
전체 흐름을 제어하거나 이벤트에 응답하는 역할을 한다.
⭕ 예시:
class EngineController {
public:
void startEngine() {
// 엔진 구동을 제어하는 로직
}
};
- EngineController 클래스는 자동차의 엔진 동작을 "제어"하는 역할을 한다.
- 이런 클래스는 직접 동작하지는 않지만, 전체 흐름을 지휘한다.
2) 클래스 간 상속이란?
- 상속(Inheritance)이란 한 클래스가 다른 클래스의 기능을 물려받는 기능이다.
- 상속을 통해 기존 클래스의 코드 재사용과 기능 확장이 가능하다.
⭕ 주요 용어 정리
1️⃣ 기초 클래스(Base Class): 상속을 제공하는 클래스이다.
- 다른 이름: 부모 클래스, 상위 클래스, 슈퍼 클래스(super class)
2️⃣ 유도 클래스(Derived Class): 상속을 받는 클래스이다.
- 다른 이름: 자식 클래스, 하위 클래스, 서브 클래스(sub class)
✅ 상속을 받은 유도 클래스는 기초 클래스의 멤버 변수와 멤버 함수를 모두 물려받는다.
2) 상속의 문법 구조
- 기본적인 상속 문법은 다음과 같다:
class 유도클래스명 : public 기초클래스명
- 예시: class Ex2 : public Ex;
3) 생성자와 초기화
- 유도 클래스는 기초 클래스의 생성자 호출을 통해 초기화를 수행해야 한다.
- 이니셜라이저(initializer)를 사용하여 기초 클래스 생성자 호출을 명시할 수 있다.
⭕ 예시 문법
Ex2(int a, int b) : Ex(a), b(b) { }
⭕ 객체 생성 순서
1️⃣ 메모리 공간 할당
2️⃣ 유도 클래스 생성자 호출 시작 (이니셜라이저 리스트 평가)
3️⃣ 기초 클래스 생성자 호출 및 실행
4️⃣ 기초 클래스 멤버 변수 초기화
5️⃣ 유도 클래스 생성자 본문 실행 및 멤버 변수 초기화
6️⃣ 객체 생성
⭕ 객체 소멸 순서
1️⃣ 유도 클래스 소멸자 호출
2️⃣ 기초 클래스 소멸자 호출
3️⃣ 기초 클래스 소멸
4️⃣ 유도 클래스 소멸
⚠️ 생성자는 두 번 호출되며, 소멸자도 역순으로 두 번 호출된다.
2. 접근 범위에 따른 상속
클래스의 멤버 접근 범위는 다음과 같이 정리된다:
✅ 접근 권한 크기: public > protected > private
1) protected 상속
- 클래스 외부에서는 접근 불가
- 유도 클래스 내부에서는 접근 가능
- 기초 클래스와 유도 클래스 사이에서도 정보 은닉 원칙을 지키는 것이 좋으므로 자주 사용되지는 않는다.
⛏️ 사용 예시:
class Derived : protected Base;
⭕ 동작 정리
- 기초 클래스의 public, protected 멤버는 모두 protected로 상속
- private 멤버는 상속되어도 접근 불가
2) private 상속
- 기초 클래스의 public, protected 멤버를 모두 private으로 상속
- 오직 유도 클래스 내부에서만 접근 가능
- ❗ 이 유도 클래스를 다시 상속할 경우, 상속받은 멤버는 접근할 수 없다 → 재상속 의미 없음
⛏️ 사용 예시:
class Derived : private Base;
3) public 상속
- 가장 일반적인 상속 방식
- 기초 클래스의 접근 범위를 그대로 유지하여 상속
⛏️ 사용 예시:
class Derived : public Base;
⭕ 동작 정리
- private 멤버 → 접근 불가
- protected 멤버 → protected로 상속
- public 멤버 → public으로 상속
3. 상속 조건
1) IS-A 관계 (상속에 적합한 관계)
- 의미: "~는 ~이다."
- 예시: 고양이는 동물이다 → Cat is a Animal
- ✅ 유도 클래스가 기초 클래스에 포함되는 개념일 때 의미 있는 상속이 된다.
2) HAS-A 관계 (상속보다는 포함 관계에 적합)
- 의미: "~는 ~를 가진다."
- 예시: 자동차는 엔진을 가진다 → Car has an Engine
⚠️ HAS-A 관계는 상속보다는 구성(composition)으로 표현하는 것이 일반적이다.
✅ 모든 유도 클래스가 기초 클래스를 필수적으로 가져야 할 경우에만 HAS-A 관계로 상속을 고려한다.
⭕ 예시 비교
- 책상은 서랍을 가진다 → ❌ 서랍 없는 책상 불가 → 상속 부적합
- 자동차는 엔진을 가진다 → ✅ 엔진은 필수 → 상속 고려 가능
✅ 마무리 정리
1️⃣ 상속은 코드 재사용과 기능 확장을 위해 사용한다.
2️⃣ 기초 클래스는 부모 역할을 하고, 유도 클래스는 자식 역할을 한다.
3️⃣ 생성자와 소멸자는 반드시 호출 순서에 유의해야 한다.
4️⃣ 접근 범위에 따라 상속 방식이 다르고, 재상속 가능 여부도 달라진다.
5️⃣ IS-A 관계일 때만 상속이 의미 있으며, HAS-A는 구성으로 처리하는 것이 일반적이다.
💻 예제 코드
#include <iostream>
using namespace std;
// 기초 클래스 정의
class Animal {
protected:
string name;
public:
Animal(string n) {
name = n;
cout << "Animal 생성자 호출" << endl;
}
void speak() {
cout << name << "이(가) 소리를 낸다." << endl;
}
~Animal() {
cout << "Animal 소멸자 호출" << endl;
}
};
// 유도 클래스 정의
class Dog : public Animal {
public:
Dog(string n) : Animal(n) {
cout << "Dog 생성자 호출" << endl;
}
void bark() {
cout << name << "이(가) 짖는다." << endl;
}
~Dog() {
cout << "Dog 소멸자 호출" << endl;
}
};
int main() {
Dog myDog("멍멍이");
myDog.speak(); // 기초 클래스 메서드 호출
myDog.bark(); // 유도 클래스 메서드 호출
return 0;
}
🖥️ 실행 결과
Animal 생성자 호출
Dog 생성자 호출
멍멍이이(가) 소리를 낸다.
멍멍이이(가) 짖는다.
Dog 소멸자 호출
Animal 소멸자 호출
'Language > C++' 카테고리의 다른 글
| 📌 Chapter 09 - 가상 (0) | 2025.09.02 |
|---|---|
| 📌 Chapter 08 - 객체 포인터와 가상 함수의 이해 (1) | 2025.08.28 |
| 📌 Chapter 06 - 특수 멤버와 한정자(Special Member & Specifier) (1) | 2025.08.25 |
| 📌 Chapter 05 - 복사 생성자(Copy Constructor) (2) | 2025.08.11 |
| 📌 Chapter 04 - 클래스 고급 개념 - 02 (4) | 2025.08.09 |