가상함수와 관련된..

J·2025년 11월 30일

테스트

목록 보기
9/12

__purecall과 가상함수 에서 얘기했던 내용과 effective c++ 의 항목 27에서

이 두 포인터의 값이 같지 않을 때가 있으며, 이때 포인터의 변위를 Derived 에 적용하여 실제의 Base를 구하는 동작이 런타임에 이루어진다고 설명한다.

class Base{ ... };
class Derived : public Base { ... };
Derived d;
Base *pb = &d;

C++에서는 다중 상속이 되면 이런 현상이 항상 생기지만, 단일 상속인데도 위 동작이 이루어지는 경우가 있다고 설명해서 그 상황 중 하나가 혹시 이런 부분이 아닐까? 라고 생각해서 간단하게 테스트해봤다.

다중상속, rtti에 대해서는 fundamental c++ 책에 나와있는 것같은데 그 부분을 학습한 뒤 테스트 내용에 추가할 예정이다.

포인터값을 런타임에 구하기 - 단일 상속

그 상황 중 하나가 Base 클래스 (가상 함수 x) 를 상속받는 Derived 클래스 (가상 함수 o)의 형태를 Base / Derived로 접근할 때

// ------------------------ 단일 상속에서 ------------------------
// Derived객체에 대해 Base*와 Derived*가 다른 경우


class Base
{
public:
	void BaseFunc() { printf("BaseFunc\n"); };

	void constFuncCall() const {}
private:
	int a = 0x11223344;
};

class DerivedB : public Base
{
public:
	virtual void BF() {}
};

int main()
{
	Base b;
	DerivedB derivedB;
	
    // static_cast<Base*> / static_cast<Derived*>를 깜빡..
	Base* pb = &derivedB; 		
	DerivedB* pd = &derivedB;   
}

ecx셋팅 후 생성자를 호출하는 과정이다.

Base 객체 생성 시

Derived 객체 생성 시

base 클래스는 가상 함수를 가지지 않고, derived 클래스부터 가상 함수를 가지기 때문에 derived 객체를 생성하면 vptr 공간을 만들어 놓고 그 뒤부터 base객체로 생성한다.

Base 객체와 derivedB 객체의 메모리공간은 다르게 생성된다.

Base 클래스 (가상 함수 x) 를 상속받는 Derived 클래스 (가상 함수 o) 인 경우의 객체 생성에 대해서 알아보았다.

그렇다면 저 Derived 클래스에 대해 Base와 Derived가 어떻게 다를까?

Base* pb = &derivedB;

의 경우 derived 객체의 주소를 받아다 4만큼 (32bit 실행, vptr 주소) 이동한 주소를 저장하는 것을 볼 수 있다.

DerivedB* pd = &derivedB;

derived 객체의 주소를 그대로 받아다 사용한다.

다중 상속

profile
낙서장

0개의 댓글