Topic 1: 상속의 기본 개념 👨👦
🎯 학습 목표
- 상속의 개념과 필요성을 이해할 수 있다
- 기본 클래스와 파생 클래스를 구분할 수 있다
- 상속 접근 지정자를 적절히 사용할 수 있다
- is-a 관계를 이해하고 설계에 적용할 수 있다
👨👩👧👦 가족 관계로 이해하는 상속
상속(Inheritance)은 가족 관계와 매우 비슷합니다!
부모와 자식의 관계 🧬
- 부모 (기본 클래스): 물려주는 클래스
- 자식 (파생 클래스): 물려받는 클래스
// 부모님으로부터 물려받는 것들
// - 성씨 (속성)
// - 외모 (속성)
// - 재능 (기능)
// - 성격 (특성)
class Parent {
string lastName; // 성씨
string eyeColor; // 눈 색깔
void walk(); // 걷기 능력
};
class Child : public Parent {
// 부모님의 모든 것을 물려받고
// + 자신만의 특징도 추가!
string nickname; // 별명 (자신만의 속성)
void playGame(); // 게임하기 (자신만의 기능)
};🌳 is-a 관계의 이해
상속은 “~는 ~이다” (is-a) 관계를 나타냅니다!
올바른 상속 관계 ✅
- 🐕 강아지는 동물이다 (Dog is-a Animal)
- 🚗 스포츠카는 자동차다 (SportsCar is-a Car)
- 👨🎓 학생은 사람이다 (Student is-a Person)
잘못된 상속 관계 ❌
- 🚗 자동차는 엔진이다? (Car is-a Engine) ❌
- 🏠 집은 방이다? (House is-a Room) ❌ → 이런 경우는 포함(has-a) 관계!
📝 기본 상속 문법
#include <iostream>
#include <string>
using namespace std;
// 기본 클래스 (부모 클래스)
class Animal {
protected: // 자식 클래스에서 접근 가능!
string name;
int age;
public:
Animal(string n = "무명", int a = 0) : name(n), age(a) {
cout << "🐾 동물 생성: " << name << endl;
}
void eat() {
cout << name << "이(가) 밥을 먹습니다 🍖" << endl;
}
void sleep() {
cout << name << "이(가) 잠을 잡니다 😴" << endl;
}
void showInfo() {
cout << "이름: " << name << ", 나이: " << age << "살" << endl;
}
};
// 파생 클래스 (자식 클래스)
class Dog : public Animal {
private:
string breed; // 견종 (Dog만의 속성)
public:
// 생성자 - 부모 생성자 호출
Dog(string n, int a, string b) : Animal(n, a), breed(b) {
cout << "🐕 강아지 생성: " << breed << endl;
}
// Dog만의 고유 기능
void bark() {
cout << name << "이(가) 짖습니다: 멍멍! 🐕" << endl;
}
void wagTail() {
cout << name << "이(가) 꼬리를 흔듭니다 🐕🦺" << endl;
}
// 정보 출력 (부모 기능 + 추가 정보)
void showDogInfo() {
showInfo(); // 부모의 함수 호출
cout << "견종: " << breed << endl;
}
};
// 또 다른 파생 클래스
class Cat : public Animal {
private:
bool isIndoor; // 실내 고양이 여부
public:
Cat(string n, int a, bool indoor) : Animal(n, a), isIndoor(indoor) {
cout << "🐱 고양이 생성" << endl;
}
// Cat만의 고유 기능
void meow() {
cout << name << "이(가) 웁니다: 야옹~ 🐱" << endl;
}
void scratch() {
cout << name << "이(가) 스크래치를 합니다 🐾" << endl;
}
void showCatInfo() {
showInfo();
cout << "실내 고양이: " << (isIndoor ? "예" : "아니오") << endl;
}
};
int main() {
cout << "=== 동물 상속 시스템 ===" << endl;
// Dog 객체 생성
Dog myDog("바둑이", 3, "진돗개");
myDog.eat(); // 부모로부터 상속받은 기능
myDog.sleep(); // 부모로부터 상속받은 기능
myDog.bark(); // Dog만의 기능
myDog.wagTail(); // Dog만의 기능
cout << endl;
myDog.showDogInfo();
cout << "\n-------------------\n" << endl;
// Cat 객체 생성
Cat myCat("나비", 2, true);
myCat.eat(); // 부모로부터 상속받은 기능
myCat.sleep(); // 부모로부터 상속받은 기능
myCat.meow(); // Cat만의 기능
myCat.scratch(); // Cat만의 기능
cout << endl;
myCat.showCatInfo();
return 0;
}🔐 상속 접근 지정자
세 가지 상속 방식
class Base {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
// 1. public 상속 (가장 일반적)
class Derived1 : public Base {
// publicVar → public
// protectedVar → protected
// privateVar → 접근 불가
};
// 2. protected 상속
class Derived2 : protected Base {
// publicVar → protected
// protectedVar → protected
// privateVar → 접근 불가
};
// 3. private 상속
class Derived3 : private Base {
// publicVar → private
// protectedVar → private
// privateVar → 접근 불가
};🎮 실습: 게임 캐릭터 계층 구조
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 기본 캐릭터 클래스
class Character {
protected:
string name;
int level;
int hp;
int maxHp;
int attackPower;
public:
Character(string n, int lv = 1)
: name(n), level(lv), hp(100), maxHp(100), attackPower(10) {
cout << "⚔️ 캐릭터 생성: " << name << endl;
}
virtual ~Character() {
cout << "💀 캐릭터 소멸: " << name << endl;
}
void basicAttack() {
cout << name << "의 기본 공격! (데미지: " << attackPower << ")" << endl;
}
void takeDamage(int damage) {
hp -= damage;
if (hp < 0) hp = 0;
cout << name << "이(가) " << damage << " 데미지를 받았습니다!" << endl;
cout << " 남은 HP: " << hp << "/" << maxHp << endl;
}
void levelUp() {
level++;
maxHp += 20;
hp = maxHp;
attackPower += 5;
cout << "🎉 " << name << " 레벨 업! (Lv." << level << ")" << endl;
}
void showStatus() {
cout << "\n=== " << name << "의 상태 ===" << endl;
cout << "레벨: " << level << endl;
cout << "HP: " << hp << "/" << maxHp << endl;
cout << "공격력: " << attackPower << endl;
}
};
// 전사 클래스
class Warrior : public Character {
private:
int armor; // 방어력
int rage; // 분노 게이지
public:
Warrior(string n) : Character(n), armor(15), rage(0) {
maxHp = 150; // 전사는 HP가 더 많음
hp = maxHp;
attackPower = 15;
cout << "🛡️ 전사 클래스 선택!" << endl;
}
// 전사 고유 스킬
void powerStrike() {
if (rage >= 30) {
cout << "💥 " << name << "의 파워 스트라이크!" << endl;
cout << " 강력한 일격! (데미지: " << attackPower * 2 << ")" << endl;
rage -= 30;
} else {
cout << "❌ 분노가 부족합니다! (현재: " << rage << "/30)" << endl;
}
}
void defend() {
cout << "🛡️ " << name << "이(가) 방어 자세를 취합니다!" << endl;
cout << " 방어력 +" << armor << endl;
rage += 10;
}
void showWarriorStatus() {
showStatus();
cout << "방어력: " << armor << endl;
cout << "분노: " << rage << "/100" << endl;
}
};
// 마법사 클래스
class Mage : public Character {
private:
int mp;
int maxMp;
int spellPower;
public:
Mage(string n) : Character(n), mp(100), maxMp(100), spellPower(25) {
maxHp = 70; // 마법사는 HP가 적음
hp = maxHp;
attackPower = 5;
cout << "🧙 마법사 클래스 선택!" << endl;
}
// 마법사 고유 스킬
void fireball() {
if (mp >= 20) {
cout << "🔥 " << name << "의 파이어볼!" << endl;
cout << " 화염 마법! (데미지: " << spellPower << ")" << endl;
mp -= 20;
} else {
cout << "❌ 마나가 부족합니다! (현재: " << mp << "/20)" << endl;
}
}
void heal() {
if (mp >= 15) {
int healAmount = 30;
hp += healAmount;
if (hp > maxHp) hp = maxHp;
mp -= 15;
cout << "💚 " << name << "의 치유 마법!" << endl;
cout << " HP +" << healAmount << " (현재: " << hp << "/" << maxHp << ")" << endl;
} else {
cout << "❌ 마나가 부족합니다!" << endl;
}
}
void meditate() {
mp += 20;
if (mp > maxMp) mp = maxMp;
cout << "🧘 " << name << "이(가) 명상합니다..." << endl;
cout << " MP +20 (현재: " << mp << "/" << maxMp << ")" << endl;
}
void showMageStatus() {
showStatus();
cout << "MP: " << mp << "/" << maxMp << endl;
cout << "주문력: " << spellPower << endl;
}
};
int main() {
cout << "=== RPG 캐릭터 시스템 ===" << endl;
// 전사 생성 및 테스트
cout << "\n--- 전사 테스트 ---" << endl;
Warrior warrior("아서");
warrior.basicAttack();
warrior.defend();
warrior.defend();
warrior.defend();
warrior.powerStrike();
warrior.levelUp();
warrior.showWarriorStatus();
// 마법사 생성 및 테스트
cout << "\n--- 마법사 테스트 ---" << endl;
Mage mage("멀린");
mage.basicAttack();
mage.fireball();
mage.takeDamage(30);
mage.heal();
mage.meditate();
mage.fireball();
mage.showMageStatus();
// 다형성 미리보기
cout << "\n--- 다형성 미리보기 ---" << endl;
Character* party[2];
party[0] = new Warrior("전사1");
party[1] = new Mage("마법사1");
for (int i = 0; i < 2; i++) {
party[i]->basicAttack();
party[i]->levelUp();
}
// 메모리 정리
delete party[0];
delete party[1];
return 0;
}📊 상속의 장점
1. 🔄 코드 재사용
- 부모 클래스의 코드를 다시 작성할 필요 없음
- 공통 기능을 한 곳에서 관리
2. 🏗️ 계층 구조
- 논리적인 관계를 코드로 표현
- 실제 세계의 관계를 모델링
3. 🔧 유지보수
- 부모 클래스만 수정하면 모든 자식에 반영
- 일관성 있는 인터페이스
4. 🎨 확장성
- 새로운 기능을 쉽게 추가
- 기존 코드를 건드리지 않고 확장
💡 핵심 정리
- 상속: 기존 클래스를 확장하여 새 클래스 생성
- 기본 클래스: 부모 클래스, 상위 클래스
- 파생 클래스: 자식 클래스, 하위 클래스
- is-a 관계: 상속의 기본 원칙
- protected: 자식 클래스에서 접근 가능한 접근 지정자
✅ 실습 체크리스트
🚀 다음 시간 예고
다음 시간에는 가상 함수와 동적 바인딩에 대해 알아볼 거예요!
- virtual 키워드의 마법
- 오버라이딩
- 다형성의 실현
“상속으로 더 효율적인 코드를 만드세요! 🧬”
Last updated on