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

타입·2024년 1월 16일
0

C++ 공부

목록 보기
5/17

this call

  • 멤버 데이터는 객체당 한 개씩 생성
    멤버 함수는 코드 메모리에 한 개만 만들어짐
    멤버 함수 호출 시 객체의 주소가 같이 전달 (this call)

  • static 멤버 함수와 this
    static 멤버 함수는 객체의 주소가 전달되지 않음 (this call 아님)
    따라서 static 멤버 함수 내에서 static이 아닌 멤버 변수는 접근 불가능

class Point
{
	int x{ 0 };
	int y{ 0 };
public:
	void set(int a, int b) // void set(Point* this, int a, int b)
	{
		x = a; // this->x = a;
		y = b; // this->y = b;
	}
	static void foo(int a)
	{
		x = a; // 컴파일 에러, static이 아닌 멤버 변수는 접근 불가능
	}
};
int main()
{
	Point pt;
	pt.set(10, 20); // set(&pt, 10, 20)

	Point::foo(10);
	pt.foo(10); // 객체를 가지고 호출해도 객체의 주소를 넘기지 않음
}

멤버 함수 포인터

  • 일반 함수 포인터와 멤버 함수 포인터
    일반 함수 포인터에 멤버 함수의 주소를 담을 수 없음
    일반 함수 포인터에 static 멤버 함수는 담을 수 있음
class X
{
public:
	       void mf1(int a) {} // void mf1(X* this, int a) {}
	static void mf2(int a) {}
};
void foo(int a) {}
int main()
{
	void(*f1)(int) = &foo; // 일반 함수 포인터
//	void(*f1)(int) = foo; // 함수 이름은 함수 주소로 암시적 변환 가능

//	void(*f2)(int) = &X::mf1; // 컴파일 에러, 일반 함수 포인터에 담을 수 없음
	void(X::*f2)(int) = &X::mf1; // 멤버 함수 포인터
	void(*f3)(int) = &X::mf2;
}
  • Pointer To Member 연산자 [ .* ]
    멤버에 대한 포인터(멤버 변수 포인터, 멤버 함수 포인터)를 사용해서 멤버에 접근할 때 사용하는 연산자
    객체가 포인터인 경우 [ ->* ]
int main()
{
	void(X::*f2)(int) = &X::mf1;
    
    X obj;
//	obj.*f2(10); // 괄호 연산자 우선순위가 높아 컴파일 에러
    (obj.*f2)(10); // pointer to member 연산자
}
  • std::invoke (C++17)
    일반 함수 포인터와 멤버 함수 포인터(callable object)를 동일한 방법으로 호출
#include <functional>

int main()
{
	...
	std::invoke(f1, 10);      // f1(10)
	std::invoke(f2, obj,  10);
	std::invoke(f2, &obj, 10);
}
  • std::mem_fn (C++11)
    멤버 함수의 주소를 인자로 받아서 함수 주소를 담은 래퍼 객체 반환
#include <functional>

int main()
{
	auto f3 = std::mem_fn(&X::mf1);
	f3(obj, 10);
	f3(&obj, 10);
}

근데 invoke()를 더 많이 사용함

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

0개의 댓글