접근 지정자 (public, protected, private)
→ 클래스 내부 멤버(변수, 함수)의 접근 범위를 정함.
• public: 누구나 접근 가능
• protected: 자식 클래스에서 접근 가능, 외부에서는 불가
• private: 자식도 접근 불가, 내부에서만 사용 가능
→ 부모 클래스의 멤버들을 자식 클래스에 어떤 접근 수준으로 물려줄지를 결정
부모 클래스의 멤버가 protected일 경우
→ 자식 클래스에서 직접 접근 가능
부모 클래스의 멤버가 private일 경우
→ 자식 클래스에서는 직접 접근 불가
→ 초기화 리스트에서 부모 생성자를 호출해 초기화해야 함
📌 1. 다형성의 개념
📌 2. 오버라이딩(Overriding)
class Shape {
public:
virtual void show(); // 가상 함수
};
class Triangle : public Shape {
public:
void show() override; // 오버라이딩
};
📌 3. 업캐스팅과 다형성
Triangle t;
Shape &s = t; // 업캐스팅
s.show(); // 🔸 Triangle::show() 호출 (다형성 발동: virtual 필요)
📌 4. 포인터로 업캐스팅한 경우도 동일
Triangle t;
Shape *s = &t;
s->show(); // 🔸 virtual 없으면 Shape::show() 호출
📌 5. 다운캐스팅의 위험성
Shape* s = new Shape;
Triangle* t = static_cast<Triangle*>(s); // ❌ 위험함 (메모리 구조 다름)
❗ Shape는 Triangle이 가진 base, height 멤버를 갖지 않으므로 잘못된 메모리 접근 발생 가능
📌 6. virtual 함수 관련 정리
class Shape {
public:
virtual void show();
};
class Triangle : public Shape {
public:
void show() override; // 명시적으로 override
};
Animal* a = new Dog();
a->speak();
- a는 Animal* 타입이지만, 실제 객체는 Dog
- a의 VPTR은 Dog의 V-Table을 가리킴
- speak() 호출 시 컴파일러는 VPTR → V-Table → speak 주소로 이동
- 결과적으로 Dog::speak()가 호출됨
👉 이게 바로 동적 바인딩(dynamic dispatch)입니다.
✅ 정적 바인딩과의 차이
좋습니다! 😊
이번엔 C++의 객체지향에서 매우 중요한 두 개념:
순수 가상 함수(Pure Virtual Function)와 가상 소멸자(Virtual Destructor)에 대해
개념 → 사용 목적 → 문법 → 예제 → 실무에서의 필요성까지 자세히 알려드릴게요!
✅ 개념
순수 가상 함수는 자식 클래스가 반드시 재정의해야 하는 가상 함수입니다.
이 함수가 하나라도 포함된 클래스는 추상 클래스(abstract class)가 됩니다.
✅ 문법
virtual 반환형 함수이름(매개변수) = 0;
예:
class Shape {
public:
virtual void draw() = 0; // 순수 가상 함수
};
✅ 특징
✅ 사용 예제
class Shape {
public:
virtual void draw() = 0; // 순수 가상 함수
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "원을 그립니다.\n";
}
};
Shape* s = new Circle();
s->draw(); // 출력: 원을 그립니다.
✅ 언제 쓰나?
✅ 개념
부모 클래스의 소멸자를 virtual로 선언하면,
자식 객체를 부모 포인터로 삭제할 때 자식의 소멸자도 제대로 호출됩니다.
✅ 왜 필요할까?
C++에서는 소멸자가 virtual이 아니면,
부모 포인터로 자식을 delete할 때 자식의 소멸자가 호출되지 않습니다.
→ 자식에서 할당한 리소스 누수 발생 가능
✅ 예제
class Shape {
public:
virtual ~Shape() {
std::cout << "Shape 소멸자\n";
}
};
class Triangle : public Shape {
public:
~Triangle() {
std::cout << "Triangle 소멸자\n";
}
};
int main() {
Shape* s = new Triangle();
delete s; // ✅ 자식 소멸자 먼저, 부모 소멸자 순서로 호출됨
}
🔸 출력
Triangle 소멸자
Shape 소멸자
❌ 만약 Shape의 소멸자가 virtual이 아니라면?