상속(Inheritance)

2025. 3. 28. 00:00Programming Languages/C++

5.5 상속(Inheritance)

5.5.1 상속의 기본 개념

상속은 기존 클래스(기본 클래스/부모 클래스)의 특성을 새 클래스(파생 클래스/자식 클래스)가 물려받는 메커니즘입니다:

#include <iostream>
#include <string>

// 기본 클래스
class Person {
protected:
    std::string name;
    int age;
    
public:
    Person(const std::string& n, int a) : name(n), age(a) {}
    
    void introduce() const {
        std::cout << "이름: " << name << ", 나이: " << age << std::endl;
    }
};

// 파생 클래스
class Student : public Person {
private:
    std::string school;
    double gpa;
    
public:
    Student(const std::string& n, int a, const std::string& s, double g)
        : Person(n, a), school(s), gpa(g) {}
    
    void study() const {
        std::cout << name << "이(가) " << school << "에서 공부합니다." << std::endl;
    }
    
    void showGPA() const {
        std::cout << "학점: " << gpa << std::endl;
    }
};

int main() {
    Person person("홍길동", 30);
    person.introduce();
    
    Student student("김철수", 20, "서울대학교", 3.8);
    student.introduce();  // 기본 클래스에서 상속받은 메서드
    student.study();      // 파생 클래스의 메서드
    student.showGPA();    // 파생 클래스의 메서드
    
    return 0;
}

5.5.2 상속 접근 지정자

상속 시 사용할 수 있는 세 가지 접근 지정자:

  1. public 상속: 기본 클래스의 public 멤버는 파생 클래스에서도 public, protected 멤버는 protected로 유지
  2. protected 상속: 기본 클래스의 public, protected 멤버 모두 파생 클래스에서 protected로 변경
  3. private 상속: 기본 클래스의 public, protected 멤버 모두 파생 클래스에서 private로 변경
// public 상속
class PublicDerived : public Base {
    // Base의 public 멤버 → PublicDerived의 public 멤버
    // Base의 protected 멤버 → PublicDerived의 protected 멤버
    // Base의 private 멤버 → 접근 불가
};

// protected 상속
class ProtectedDerived : protected Base {
    // Base의 public 멤버 → ProtectedDerived의 protected 멤버
    // Base의 protected 멤버 → ProtectedDerived의 protected 멤버
    // Base의 private 멤버 → 접근 불가
};

// private 상속
class PrivateDerived : private Base {
    // Base의 public 멤버 → PrivateDerived의 private 멤버
    // Base의 protected 멤버 → PrivateDerived의 private 멤버
    // Base의 private 멤버 → 접근 불가
};

5.5.3 다중 상속(Multiple Inheritance)

C++에서는 클래스가 여러 기본 클래스로부터 상속받을 수 있습니다:

#include <iostream>
#include <string>

// 첫 번째 기본 클래스
class Animal {
protected:
    std::string name;
    
public:
    Animal(const std::string& n) : name(n) {}
    
    void eat() const {
        std::cout << name << "이(가) 먹고 있습니다." << std::endl;
    }
};

// 두 번째 기본 클래스
class Vehicle {
protected:
    int wheels;
    
public:
    Vehicle(int w) : wheels(w) {}
    
    void move() const {
        std::cout << wheels << "개의 바퀴로 움직입니다." << std::endl;
    }
};

// 다중 상속
class Horse : public Animal {
public:
    Horse(const std::string& n) : Animal(n) {}
    
    void gallop() const {
        std::cout << name << "이(가) 달립니다." << std::endl;
    }
};

class Bird : public Animal {
public:
    Bird(const std::string& n) : Animal(n) {}
    
    void fly() const {
        std::cout << name << "이(가) 날아갑니다." << std::endl;
    }
};

// 다중 상속 예제
class Pegasus : public Horse, public Bird {
public:
    Pegasus(const std::string& n) : Horse(n), Bird(n) {}
};

int main() {
    Pegasus pegasus("페가수스");
    
    // 다중 상속으로 인한 모호성
    // pegasus.eat();  // 오류: 'eat' 멤버가 'Horse'와 'Bird' 모두에서 발견됨
    
    // 범위 지정 연산자로 모호성 해결
    pegasus.Horse::eat();
    pegasus.gallop();
    pegasus.Bird::fly();
    
    return 0;
}

다중 상속의 문제점:

  • 다이아몬드 문제(Diamond Problem): 두 기본 클래스가 같은 부모 클래스를 상속할 때 발생
  • 모호성: 동일한 이름의 메서드나 멤버가 여러 기본 클래스에 존재할 경우

5.5.4 가상 상속(Virtual Inheritance)

다이아몬드 문제를 해결하기 위한 방법:

#include <iostream>
#include <string>

// 최상위 기본 클래스
class Animal {
protected:
    std::string name;
    
public:
    Animal(const std::string& n) : name(n) {
        std::cout << "Animal 생성자 호출" << std::endl;
    }
    
    void eat() const {
        std::cout << name << "이(가) 먹고 있습니다." << std::endl;
    }
};

// 가상 상속을 사용한 중간 클래스
class Mammal : virtual public Animal {
public:
    Mammal(const std::string& n) : Animal(n) {
        std::cout << "Mammal 생성자 호출" << std::endl;
    }
    
    void breathe() const {
        std::cout << name << "이(가) 폐로 숨을 쉽니다." << std::endl;
    }
};

// 가상 상속을 사용한 또 다른 중간 클래스
class WingedAnimal : virtual public Animal {
public:
    WingedAnimal(const std::string& n) : Animal(n) {
        std::cout << "WingedAnimal 생성자 호출" << std::endl;
    }
    
    void flap() const {
        std::cout << name << "이(가) 날개를 펄럭입니다." << std::endl;
    }
};

// 다이아몬드 상속 구조의 맨 아래 클래스
class Bat : public Mammal, public WingedAnimal {
public:
    Bat(const std::string& n) : Animal(n), Mammal(n), WingedAnimal(n) {
        std::cout << "Bat 생성자 호출" << std::endl;
    }
};

int main() {
    std::cout << "박쥐 객체 생성:" << std::endl;
    Bat bat("브루스");
    
    // 가상 상속으로 모호성 해결
    bat.eat();      // Animal::eat() 호출, 모호성 없음
    bat.breathe();  // Mammal::breathe() 호출
    bat.flap();     // WingedAnimal::flap() 호출
    
    return 0;
}

 

'Programming Languages > C++' 카테고리의 다른 글

챕터5. 실습 문제  (0) 2025.03.28
다형성(Polymorphism)  (0) 2025.03.28
객체 생성과 수명 주기  (0) 2025.03.28
생성자와 소멸자  (0) 2025.03.28
캡슐화와 접근 지정자  (0) 2025.03.28