[Class의 상속] 재사용성과 확장성을 높이는 객체지향의 핵심
Class의 상속
C++은 객체지향 언어로서 클래스와 상속 개념을 기반으로 코드의 재사용성, 확장성, 유지보수성을 높일 수 있는 기능을 제공합니다. C++에서 상속을 사용하면, 기존 클래스의 멤버(변수 및 함수)를 자식 클래스가 그대로 물려받아 사용할 수 있으며, 필요 시 오버라이딩(overriding)을 통해 일부 기능을 수정하거나 확장할 수 있습니다.
이 글에서는 C++에서 클래스 상속이 어떻게 사용되는지에 대한 전반적인 내용을 다룹니다. 기본 문법은 물론, 접근 제어자(public, protected, private), 가상 함수(virtual function), 다형성(polymorphism), 다중 상속(multiple inheritance)까지 C++에서 자주 쓰이는 상속 개념을 자세히 살펴보겠습니다.
1. C++에서의 클래스 상속 기본 문법
// 부모 클래스
class Animal {
public:
void eat() {
std::cout << "먹이를 먹습니다." << std::endl;
}
};
// 자식 클래스
class Dog : public Animal {
public:
void bark() {
std::cout << "멍멍!" << std::endl;
}
};
int main() {
Dog d;
d.eat(); // 부모 클래스의 메서드
d.bark(); // 자식 클래스의 메서드
return 0;
}
- Dog는 Animal을 public 상속 받습니다. 이로 인해 Animal의 public 멤버 를 그대로 사용할 수 있습니다.
- 상속 시 사용되는 접근 지정자에 따라 부모 멤버의 접근 권한이 변경됩니다.
2. 접근 지정자에 따른 상속 방식
상속 키워드 | 부모의 public 멤버 | 부모의 protected 멤버 | 부모의 private 멤버 |
public 상속 | public | protected | 상속되지 않음 |
protected 상속 | protected | protected | 상속되지 않음 |
private 상속 | private | private | 상속되지 않음 |
class Base {
public:
int pub;
protected:
int prot;
private:
int priv;
};
class Derived : public Base {
// pub → pub, prot → prot, priv → 상속 안 됨
};
3. 함수 오버라이딩 (overriding) 과 가상 함수 (Virtual Function)
C++에서는 부모 클래스의 함수를 자식 클래스에서 재정의할 수 있습니다. 이때 함수가 virtual로 선언되어 있어야 런타임에서의 다형성이 제대로 작동합니다.
class Animal {
public:
virtual void speak() {
std::cout << "동물이 소리냅니다." << std::endl;
}
};
class Dog : public Animal {
public:
void speak() override {
std::cout << "멍멍!" << std::endl;
}
};
void makeSound(Animal* a) {
a->speak(); // 가상 함수이므로 실제 객체 타입에 따라 호출
}
int main() {
Dog d;
makeSound(&d); // 멍멍!
}
왜 virtual이 중요한가?
- 가상 함수 없이 speak()를 정의하면, 포인터가 Animal*인 이상 항상 부모 클래스의 함수만 호출됩니다.
- virtual을 붙이면 다형성이 적용되어 자식 클래스의 함수가 호출됩니다.
4. 다형성과 상속의 관계
C++에서는 상속을 통해 다형성(polymorphism)을 구현할 수 있습니다. 부모 클래스 포인터 또는 참조로 자식 클래스 객체를 다룰 수 있는 유연성을 제공하죠.
std::vector<Animal*> animals;
animals.push_back(new Dog());
animals.push_back(new Cat());
for (auto a : animals) {
a->speak(); // 각각 멍멍!, 야옹!
}
- 주의 : C++에서는 delete 호출 시 메모리 누수를 방지하기 위해 소멸자도 virtual로 선언하는 것이 좋습니다.
class Animal {
public:
virtual ~Animal() {} // virtual 소멸자
};
5. 다중 상속 (Multiple Inheritance)
C++은 여러 클래스로부터 동시에 상속받을 수 있는 다중 상속을 지원합니다.
class Flyer {
public:
void fly() {
std::cout << "날아갑니다!" << std::endl;
}
};
class Swimmer {
public:
void swim() {
std::cout << "수영합니다!" << std::endl;
}
};
class Duck : public Flyer, public Swimmer {
// Duck은 fly()와 swim()을 둘 다 가짐
};
다이아몬드 상속 문제와 가상 상속
다중 상속 시 동일한 상위 클래스가 중복 상속되면 다이아몬드 문제가 발생할 수 있으며, 이를 해결하기 위해 가상 상속(virtual inheritance)이 사용됩니다.
class Animal {
public:
void live() { std::cout << "생존 중!" << std::endl; }
};
class Mammal : virtual public Animal {};
class WingedAnimal : virtual public Animal {};
class Bat : public Mammal, public WingedAnimal {};
6. 마무리
C++에서 클래스 상속은 코드 재사용과 확장을 가능하게 해주는 객체지향의 핵심 개념입니다.
- public, protected, private 상속 : 접근 수준에 따라 상속 방식이 달라집니다.
- 가상 함수와 다형성 : 런타임에서 객체의 실제 타입에 따라 함수 호출이 가능합니다.
- virtual 소멸자 : 메모리 누수를 막기 위한 필수 개념입니다.
- 다중 상속과 가상 상속 : C++만의 유연한 구조 설계 가능하지만 신중히 사용해야 합니다.
함께 보면 좋은 자료
블로그 글 :
[Class] 객체지향 프로그래밍의 핵심
클래스(Class) C++는 절차적 프로그래밍과 객체지향 프로그래밍(OOP)을 모두 지원하는 다중 패러다임 언어입니다. 그중 클래스(class)는 객체지향 프로그래밍의 핵심 개념으로, 데이터와 관련된 동작
dachaes-devlogs.tistory.com
[Class와 Struct] 클래스와 구조체의 차이
클래스(Class)와 구조체(Struct)C++에서 Class와 Struct는 둘 다 사용자 정의 타입을 만들기 위한 도구입니다. 많은 초보자들이 C++에서 Class와 Struct를 혼용할 수 있다는 사실에 놀라지만, 실제로 이 둘은
dachaes-devlogs.tistory.com