C++ 중급 - 상속과 멤버 함수 포인터

타입·2024년 2월 6일
0

C++ 공부

목록 보기
7/17

멤버 함수 포인터의 크기

  • 다중 상속과 this
    기반 클래스 포인터로 파생 클래스 객체를 가리킬 때 객체 안에 있는 기반 클래스 위치를 가리킴
    다중 상속일 경우 객체의 주소와 다를 수 있음
struct A { int x;};
struct B { int y;};
struct C : public A, public B 
{
	 int z;
};
int main()
{
	C cc;
	std::cout << &cc << std::endl; // 1000 

	A* pA = &cc;
	B* pB = &cc;

	std::cout << pA << std::endl; // 1000
	std::cout << pB << std::endl; // 1004, pB를 따라가면 B의 위치를 찾을 수 있음
}

static_cast: 인자로 전달된 주소 안에서 기반 클래스의 위치가 반환, 상속관계가 아니라면 에러
reinterpret_cast: 항상 인자로 전달한 주소가 동일하게 반환, 상속관계가 아니어도 에러나지 않음, 메모리를 다르게 해석 하겠다는 뜻!

int main()
{
	...
	B* pB1 = static_cast<B*>(&cc);
	B* pB2 = reinterpret_cast<B*>(&cc);

	pB2->y = 10; // 결국 cc.x 에 대입
	std::cout << pB1 << std::endl; // 1004
	std::cout << pB2 << std::endl; // 1000
}
  • 멤버 함수 포인터와 this
struct A 
{
	int x;
	void fa() { std::cout << this << std::endl;}
};
struct B 
{
	int y;
	void fb() { std::cout << this << std::endl;}
};
struct C : public A, public B 
{
	int z;
	void fc() { std::cout << this << std::endl;}
};
int main()
{
	C cc;
	cc.fc(); // 0x1000
	cc.fa(); // 0x1000
	cc.fb(); // 0x1004

	void(C::*f)();

//	f = &C::fa; // 0x1000
	f = &C::fb; // 0x1004

	(cc.*f)();
}

f = &A::fa인 경우 f(&cc)가 되어야 하고
f = &B::fb인 경우 B를 가리켜야 하므로 f(&cc + sizeof(A))가 되어야 함

  • 멤버 함수 포인터의 크기
    항상 4byte(32bit) / 8byte(64bit)인 건 아니고 코드에 따라 멤버 함수 포인터의 크기가 달라짐
    다중 상속의 경우 함수 주소와 this offset을 같이 보관
int main()
{
	C cc;

	void(C::*f)();

	std::cout << sizeof(f) << std::endl; // 16byte(64bit)

//	f = &C::fa;
	f = &C::fb; 

	(cc.*f)(); // f.함수주소(&cc + f.this_offset)
    			// 그래서 fa일 땐 더하는게 없고, fb일때 더함

	void* p = f; // error
}

void*에는 pointer to member(멤버 함수 포인터/멤버 데이터 포인터)를 담을 수 없음
멤버 데이터의 포인터는 진짜 주소는 아니고 오프셋이기 때문

  • cout과 pointer to member
    직전에 pointer to member는 void*에 담을 수 없다 하였음
    pointer to member는 bool로 암시적 변환 가능
struct Point { int x, y;};
struct myostream
{
	myostream& operator<<(int    n) { printf("int    : %d\n", n); return *this;}	
	myostream& operator<<(double d) { printf("double : %f\n", d); return *this;}	
	myostream& operator<<(bool   b) { printf("bool   : %d\n", b); return *this;}	
	myostream& operator<<(void*  p) { printf("void*  : %p\n", p); return *this;}	
	myostream& operator<<(const char* s) { printf("char* : %s\n", s); return *this;}	
};
myostream mycout;
int main()
{
	int n = 10;
	double d = 3.4;
	int Point::*p = &Point::y; 

	mycout << n;  // int
	mycout << d;  // double
	mycout << &n; // void*
	mycout << &d; // void* 
	mycout << p;  // bool   값 4 => 1(true)
}

pointer to member의 주소를 보고 싶다면 printf를 사용하자

profile
주니어 언리얼 프로그래머

0개의 댓글