IMCAT.DEV
로그인 가입
C++ 중급 객체지향

C++ 상속 (Inheritance)

C++ 상속 (Inheritance) — 중급

상속 (Inheritance)

1. 도입 (왜 배워야 하는가)

상속은 객체 지향 프로그래밍의 핵심 개념 중 하나로, 코드의 재사용성과 확장성을 향상시키는 중요한 기법입니다. 실무에서는 상속을 통해 기본 클래스의 속성과 메서드를 기반으로 새로운 클래스를 쉽게 생성할 수 있어, 개발 효율성을 극대화합니다.

예를 들어, 쇼핑몰 애플리케이션을 개발할 때 상품이라는 기본 클래스를 만들고, 이를 상속받아 전자기기, 의류, 식품 등의 클래스를 생성할 수 있습니다. 이때 기본 클래스에서 정의한 속성(예: 가격, 이름)을 자식 클래스에서 재사용할 수 있습니다. 만약 상속을 사용하지 않는다면, 중복된 코드가 발생하고 유지보수가 어려워지며, 오류 발생 가능성이 커질 수 있습니다.

2. 핵심 개념 설명

상속이란, 기존 클래스(부모 클래스)의 특성과 동작을 새로운 클래스(자식 클래스)가 물려받는 기능을 말합니다. 상속을 통해 자식 클래스는 부모 클래스의 모든 속성과 메서드를 사용할 수 있습니다.

비유

상속은 부모가 자녀에게 유전자를 물려주는 것과 비슷합니다. 부모가 가진 특성(예: 눈 색깔, 머리 모양)을 자녀가 물려받는 것처럼, 자식 클래스는 부모 클래스의 속성과 메서드를 물려받습니다.

용어설명
부모 클래스다른 클래스의 속성과 메서드를 상속하는 클래스
자식 클래스부모 클래스를 상속받아 새로운 기능을 추가한 클래스
다중 상속하나의 자식 클래스가 여러 부모 클래스를 상속받는 것

3. 기본 코드 예제

다음은 상속의 기본 사용법을 보여주는 간단한 코드 예제입니다.

#include <iostream>
using namespace std;

// 부모 클래스
class Animal {
public:
    void speak() {
        cout << "Animal makes a sound" << endl;
    }
};

// 자식 클래스
class Dog : public Animal {
public:
    void bark() {
        cout << "Dog barks: Woof!" << endl;
    }
};

int main() {
    Dog myDog;
    myDog.speak(); // 부모 클래스의 메서드 호출
    myDog.bark();  // 자식 클래스의 메서드 호출
    return 0;
}

실행 결과

Animal makes a sound
Dog barks: Woof!

코드 한 줄씩 동작 설명

  1. #include <iostream>: 입출력 스트림을 사용하기 위해 iostream 헤더를 포함합니다.
  2. using namespace std;: std 이름공간을 사용하여 코드에서 std::를 생략할 수 있습니다.
  3. class Animal { ... };: Animal이라는 부모 클래스를 정의합니다.
  4. void speak() { ... }: Animal 클래스의 메서드로, 동물의 소리를 출력합니다.
  5. class Dog : public Animal { ... };: Dog 클래스를 정의하고, Animal 클래스를 상속받습니다.
  6. void bark() { ... }: Dog 클래스의 메서드로, 개의 울음소리를 출력합니다.
  7. int main() { ... }: 프로그램의 실행 시작점인 main 함수를 정의합니다.
  8. Dog myDog;: Dog 클래스의 객체를 생성합니다.
  9. myDog.speak();: 부모 클래스의 메서드를 호출합니다.
  10. myDog.bark();: 자식 클래스의 메서드를 호출합니다.
  11. 4. 실전 활용 예제

    예제 1: 쇼핑몰에서 장바구니 기능 구현

    #include <iostream>
    #include <vector>
    using namespace std;
    
    // 부모 클래스
    class Item {
    public:
        string name;
        double price;
    
        Item(string n, double p) : name(n), price(p) {}
    };
    
    // 자식 클래스
    class Book : public Item {
    public:
        string author;
    
        Book(string n, double p, string a) : Item(n, p), author(a) {}
    };
    
    class Cart {
    private:
        vector<Item> items;
    
    public:
        void addItem(Item item) {
            items.push_back(item);
        }
    
        void checkout() {
            double total = 0;
            for (Item* item : items) {
                total += item->price;
                cout << "Item: " << item->name << ", Price: " << item->price << endl;
            }
            cout << "Total: " << total << endl;
        }
    };
    
    int main() {
        Cart myCart;
        Book book1("C++ Programming", 29.99, "John Doe");
        myCart.addItem(&book1);
        myCart.checkout();
        return 0;
    }

    상황 설명: 쇼핑몰에서 장바구니 기능을 구현하기 위해 Item 클래스를 부모 클래스로 하고, Book 클래스를 자식 클래스로 정의하여 책 정보를 관리합니다. 장바구니에 아이템을 추가하고, 체크아웃 시 총 가격을 계산합니다.

    예제 2: 게임에서 캐릭터 구현

    #include <iostream>
    using namespace std;
    
    class Character {
    public:
        string name;
        int health;
    
        Character(string n, int h) : name(n), health(h) {}
    
        void display() {
            cout << "Character: " << name << ", Health: " << health << endl;
        }
    };
    
    class Warrior : public Character {
    public:
        int strength;
    
        Warrior(string n, int h, int s) : Character(n, h), strength(s) {}
    
        void attack() {
            cout << name << " attacks with strength " << strength << "!" << endl;
        }
    };
    
    int main() {
        Warrior warrior("Thor", 100, 50);
        warrior.display();
        warrior.attack();
        return 0;
    }

    상황 설명: 게임 개발에서 캐릭터 클래스를 부모 클래스로 하고, 전사 클래스를 자식 클래스로 정의하여 전사 캐릭터의 특성과 행동을 구현합니다.

    5. 흔한 실수와 주의사항

    실수 1: 접근 제어자

    잘못된 코드

    class Base {
    private:
        int value;
    };
    
    class Derived : public Base {
    public:
        void setValue(int v) { value = v; } // 오류: value에 접근 불가
    };

    올바른 코드

    class Base {
    protected: // protected로 변경
        int value;
    };

    실수 2: 다중 상속의 문제

    잘못된 코드

    class A {};
    class B {};
    class C : public A, public B {}; // 문제 발생 가능성

    올바른 코드

    class A {};
    class B {};
    class C : public A { 
        B b; // B를 C의 멤버로 포함
    };

    6. 정리

    • 상속은 코드 재사용과 유지보수를 용이하게 해준다.
    • 부모 클래스의 속성과 메서드를 자식 클래스가 그대로 사용할 수 있다.
    • 다중 상속은 주의가 필요하며, 필요 시에는 멤버로 포함하는 방법을 고려해야 한다.
    • 다음에 학습하면 좋은 주제

    • 다형성(Polymorphism): 상속과 함께 사용하는 중요한 개념
    • 추상 클래스(Abstract Class): 일반화된 클래스를 만들기 위한 기법
    • 인터페이스(Interface): 클래스 간의 계약을 정의하는 방법