가상함수, 바인딩

Oak_Cassia·2021년 11월 12일
0

가상함수 테이블

객체를 생성하는 코드에 브레이크 포인트를 잡고 메모리에서 객체의 주소를 보면 첫 번째 주소멤버 변수 가 차례로 위치한 것을 볼 수 있다.

Cclass Ob1(11);

위 코드를 통해 멤버 변수가 4개인 객체 생성

각 멤버변수 11(b), 1, 255(ff), 255(ff)


이때 부모 클래스에 가상함수를 추가한 뒤 다시 메모리를 보면
(컴퓨터 재시작 후 다시 컴파일 해서 주소가 변경 되었다. 실제로 같은&Ob1 값이다.)


그리고 어셈블리어를 확인하면(ctrl+atl+d)
Ob1 주소의 첫번째에 위치한 값이 vftable 즉 가상함수테이블의 주소임을 알 수 있다.(리틀 엔디안 방식의 주소라 297B44 가 44 7B 29 순으로 저장됐다.)

중간에 Pclass::Pclass 도 보이는데 부모 클래스의 생성자를 호출한 것이다.(이 때 vftable 주소가 입력되지만 마지막 줄의 명령어에 의해 덮어 쓰인다.)
해당 주소에 가보면 가상함수들을 확인할 수 있다.


가상함수

아래의 코드 중 이 함수를 보자.

void ShowInfo(Pclass* a)
{
	a->GetId();
}

객체포인터로 매개변수를 받기 때문에 자식클래스인 Cclass의 객체가 Pclass 클래스의 포인터 형식으로 전달 될 수 있다.
이 때 부모 클래스의 GetId가 호출된다.
하지만 virtual을 사용하여 GetId를 가상함수로 만들면 호출한 객체에 따라 Cclass의 함수가 호출된다.

#include <iostream>
using namespace std;

class Pclass
{
protected:
	int Id;
public:
	Pclass(int id)
	{
		Id = id;
	}
	virtual void SetId(int num)
	{
		Id = num;
	}
	const void GetId()
	{
		cout << Id << endl;
	}
};

class Cclass : public Pclass
{
	int Cid = 1; //C++11에 추가된 초기화 방법
	int fl = 0xFF;
	int f2 = 0xFF;

public:
	Cclass(int id);
	virtual void SetId(	int num) //여기서 virtual은 생략할 수 있다.
	{
		Id = num;
	}

	const void GetId()
	{
		cout << Id+1000 << endl;
	}
};

Cclass::Cclass(int id) : Pclass(id)
{

}

void ShowInfo(Pclass* a)
{
	a->GetId();
}


int main()
{
	Cclass Ob1(11);
	Ob1.SetId(99);
	ShowInfo(&Ob1);

}

바인딩

Binding refers to the process of converting identifiers into addresses.
Binding is done for each variable and functions. For functions, it means that matching the call with the right function definition by the compiler. It takes place either at compile time or at runtime.(출처-Geeks for Geeks)

이 때 컴파일 타임에 수행되면 정적 바인딩
런타임에 수행되면 동적 바인딩이라 한다.
기본적으로 c++에서는 정적바인딩이 수행되지만 가상 함수 중 부모 클래스 타입의 포인터나 참조를 통하여 호출될 경우 동적 바인딩을 한다.


순수 가상 함수

virtual void Func() = 0;
이렇게 앞에 virtual 끝에 =0 이 붙은 함수를 순수 가상 함수 라고한다.
클래스 내에 순수 가상 함수가 있으면 그 클래스를 추상클래스(abstract class) 라고한다.
추상 클래스로는 객체를 생성하지 못한다.
상속을 할 때 사용한다.
자식 클래스가 오버라이딩을 해야 한다.

C#에서는 Interface라고 함수의 선언부만 넣은 클래스를 따로 만들 수 있다.

profile
rust로 뭐할까

0개의 댓글