class Base {
int x;
public:
Base(int x = 0) : x(x) {};
};
class Derived : public Base {
int x;
public:
Derived(int x1 = 0, int x2 = 0) : Base(x1), x(x2) {};
}
};
int main() {
Derived d1(1, 2);
Base b1 = d1; // ⚠️ upcasting
//Derived d2 = b1; // error, downcasting
}
→ 자식 클래스(Derived) 객체를 부모 클래스(Base) 타입에 대입했으므로 업캐스팅(upcasting) 이다.
→ 복사 생성자에 의해 Derived 객체의 Base 부분만 b1에 복사된다. 이때 Derived 클래스의 멤버 int x는 복사되지 않고 잘린다. 이것을 객체 슬라이싱(object slicing) 이라고 한다.
자식 클래스의 객체를 부모 클래스 타입으로 변환하는 것
안전하며 자동으로 일어남
int main() {
Derived d1(1, 2); // Derived 객체 생성. Base 부분: x=1, Derived 부분: x=2
Base& b1 = d1; // ⚠️ 참조 upcasting Derived → Base 참조
d1.Print(); // Derived::Print() 호출 → 1 2 출력
b1.Print(); // Base::Print() 호출 → 1 출력
}
Base& b1 = d1;
참조 upcasting은 object slicing이 없다. 참조니까 잘려나가지 않기 때문이다.
하지만!
Print() 함수가 virtual이 아니기 때문에, b1.Print(); 는 Base 클래스의 Print() 함수만 호출된다.그래서 Base의 x 값인 1만 출력된다.
b1.Print();
정적 바인딩으로 인해 b1.Print()는 Base 클래스에 정의된 함수만 호출된다.
→ 1 출력, 2는 출력되지 않음.
→ 결과적으로 Derived 객체를 참조하고 있어도, Derived::Print()는 무시됩니다.
Base& b1 = d1;
정적 타입 = 코드에 써진 타입, 컴파일러가 보는 타입. b1은 Base 객체다.
실제 객체 타입 = 그러나 b1에 할당된 d1은 사실은 Derived 객체이다.
정적 바인딩의 컴파일러 : Print()가 virtual이 아니기 때문에, 컴파일러는 b는 Base&니까 Base::Print()를 호출하면 되겠군!
동적 바인딩의 컴파일러 : "b는 Base 타입처럼 보이지만, 실제 객체가 Derived일 수도 있네? 런타임에 결정하자!"
class Base {
public:
virtual void Print() const { std::cout << x << ' '; }
};
이렇게 하면 동적 바인딩이 된다.
b1.Print(); 도 Derived::Print() 를 호출하게 되어, 출력은 1 2 가 된다.
| 구분 | virtual 없음 | virtual 있음 |
|---|---|---|
| 호출되는 함수 | 정적 타입 기준(Base::Print) | 실제 객체 기준(Derived::Print) |
| 바인딩 방식 | 정적 바인딩 (compile time) | 동적 바인딩 (runtime) |
| b1.Print() 결과 | 1 (Base의 x만 출력) | 1 2 (Base와 Derived 모두 출력) |
virtual이 없으면 무조건 정적 바인딩이다.
virtual이 없으면 객체의 실제 타입이 뭐든지 상관없이, 참조나 포인터의 타입만 보고 컴파일 타임에 함수가 고정된다.
이 때문에 b1.Print()는 Derived를 가리켜도 무조건 Base::Print()만 호출되는 것이다.
자식 클래스의 객체를 부모 클래스 값으로 복사할 때, 부모 클래스에 없는 자식의 멤버들이 잘려나가는 현상
부모 클래스의 객체를 자식 클래스 객체로 변환하는 것
업캐스팅보다 위험하며, 명시적으로 해야함
Derived d1(1, 2); // Derived 객체 생성
Base b1 = d1; // 업캐스팅 (object slicing 발생)
Derived d2 = b1; // ❌ 다운캐스팅 (에러 발생)
❓ 왜 에러일까?
b1은 부모 클래스의 객체다. Base의 정보만 가지고 Derived를 구성해야 하는데, C++ 컴파일러는 그렇게 복원하는 방법을 알 수 없기 때문에 에러가 발생한다.