ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C++ 객체 지향 프로그래밍: 상속과 다형성
    c++ 2025. 2. 1. 18:17
    728x90

    이전 포스팅에서는 **C++ 객체 지향 프로그래밍(OOP)**의 기본 개념과 클래스, 객체에 대해 알아보았습니다. 이번 글에서는 **상속(Inheritance)**과 **다형성(Polymorphism)**이라는 두 가지 핵심 OOP 개념을 소개하고, C++에서 이를 어떻게 구현하는지 살펴보겠습니다.


    1. 상속(Inheritance)란?

    상속은 기존 클래스의 속성과 메서드를 새로운 클래스에 물려주는 기능입니다. 이를 통해 코드의 재사용성을 높이고, 유지보수를 쉽게 할 수 있습니다.

    (1) 기본 상속 구조

    • 부모 클래스(기초 클래스, Base Class): 기존 클래스
    • 자식 클래스(파생 클래스, Derived Class): 부모 클래스로부터 상속받은 새로운 클래스
    #include <iostream>
    using namespace std;
    
    // 부모 클래스
    class Animal {
    public:
        void eat() {
            cout << "먹고 있습니다." << endl;
        }
    };
    
    // 자식 클래스 (Animal을 상속받음)
    class Dog : public Animal {
    public:
        void bark() {
            cout << "멍멍!" << endl;
        }
    };
    
    int main() {
        Dog myDog;
        myDog.eat();  // 부모 클래스의 메서드 사용
        myDog.bark(); // 자식 클래스의 메서드 사용
        return 0;
    }

    (2) 출력 결과:

    먹고 있습니다.
    멍멍!

    (3) 상속의 종류

    1. 공개 상속(public inheritance): 부모 클래스의 public 멤버가 자식 클래스에서도 public으로 유지됩니다.
    2. 보호 상속(protected inheritance): 부모 클래스의 public 멤버가 자식 클래스에서 protected로 변환됩니다.
    3. 비공개 상속(private inheritance): 부모 클래스의 public 멤버가 자식 클래스에서 private으로 변환됩니다.

    2. 오버라이딩(Overriding)

    상속받은 메서드를 **자식 클래스에서 재정의(Override)**할 수 있습니다.

    class Animal {
    public:
        void sound() {
            cout << "동물이 소리를 냅니다." << endl;
        }
    };
    
    class Dog : public Animal {
    public:
        void sound() {  // 부모 클래스의 메서드를 재정의
            cout << "개가 멍멍 짖습니다." << endl;
        }
    };
    
    int main() {
        Dog myDog;
        myDog.sound();  // 자식 클래스의 sound() 호출
        return 0;
    }

    출력 결과:

    개가 멍멍 짖습니다.

    3. 다형성(Polymorphism)이란?

    다형성은 하나의 인터페이스가 여러 형태로 동작할 수 있게 하는 개념입니다. C++에서 다형성을 구현하려면 **가상 함수(virtual function)**와 포인터 또는 **참조(reference)**를 활용합니다.

    (1) 가상 함수(Virtual Function)

    가상 함수는 부모 클래스에서 선언하고, 자식 클래스에서 재정의할 수 있습니다.

    class Animal {
    public:
        virtual void sound() {  // 가상 함수
            cout << "동물이 소리를 냅니다." << endl;
        }
    };
    
    class Dog : public Animal {
    public:
        void sound() override {  // 가상 함수 재정의
            cout << "개가 멍멍 짖습니다." << endl;
        }
    };
    
    class Cat : public Animal {
    public:
        void sound() override {
            cout << "고양이가 야옹거립니다." << endl;
        }
    };
    
    int main() {
        Animal* animalPtr;
        Dog dog;
        Cat cat;
    
        animalPtr = &dog;
        animalPtr->sound();  // 개가 멍멍 짖습니다.
    
        animalPtr = &cat;
        animalPtr->sound();  // 고양이가 야옹거립니다.
    
        return 0;
    }

    (2) 출력 결과:

    개가 멍멍 짖습니다.
    고양이가 야옹거립니다.
    • virtual 키워드가 없다면 부모 클래스의 sound() 메서드가 호출됩니다.
    • override 키워드는 가상 함수를 재정의하고 있다는 것을 명시합니다.

    4. 추상 클래스(Abstract Class)와 순수 가상 함수

    (1) 추상 클래스란?

    추상 클래스는 **순수 가상 함수(pure virtual function)**를 포함한 클래스입니다. 추상 클래스는 객체로 생성할 수 없으며, 상속받은 클래스에서 반드시 해당 함수를 구현해야 합니다.

    (2) 순수 가상 함수 정의

    class Animal {
    public:
        virtual void sound() = 0;  // 순수 가상 함수
    };
    
    class Dog : public Animal {
    public:
        void sound() override {
            cout << "개가 멍멍 짖습니다." << endl;
        }
    };
    
    int main() {
        Dog myDog;
        myDog.sound();
        return 0;
    }

    (3) 출력 결과:

    개가 멍멍 짖습니다.
    • virtual void sound() = 0;순수 가상 함수를 의미합니다.
    • 추상 클래스인 Animal은 객체로 생성할 수 없습니다.

    5. 다형성의 실전 예제: 동물 소리 내기 프로그램

    #include <vector>
    
    class Animal {
    public:
        virtual void sound() = 0;  // 순수 가상 함수
    };
    
    class Dog : public Animal {
    public:
        void sound() override {
            cout << "멍멍!" << endl;
        }
    };
    
    class Cat : public Animal {
    public:
        void sound() override {
            cout << "야옹!" << endl;
        }
    };
    
    int main() {
        vector<Animal*> animals;  // Animal 포인터의 벡터
    
        animals.push_back(new Dog());
        animals.push_back(new Cat());
    
        for (Animal* animal : animals) {
            animal->sound();  // 각 동물의 소리 출력
        }
    
        // 메모리 해제
        for (Animal* animal : animals) {
            delete animal;
        }
    
        return 0;
    }

    출력 결과:

    멍멍!
    야옹!

    이렇게 다형성을 이용하면 같은 인터페이스(sound())로 다양한 객체(Dog, Cat)의 동작을 쉽게 관리할 수 있습니다.

    728x90
Designed by Tistory.