Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 12: 상속과 다형성Topic 1: 상속의 기본 개념

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