멤버 함수 포인터

일반 함수 포인터와 달리, 멤버 함수 포인터는 특별한 문법을 사용합니다.

기본 사용법

  class X {
public:
    void mf1(int);
    static void sf1(int);
};

// 일반 함수 포인터에는 static 멤버 함수만 담을 수 있음
void (*f1)(int) = &X::sf1;

// 멤버 함수 포인터
void (X::*f2)(int) = &X::mf1;

// 호출 방법
X obj;
(obj.*f2)(10);  // 객체를 통한 호출
  

문제점과 해결책

문제: 일반 함수 포인터와 멤버 함수 포인터의 호출 방식이 다름

해결책:

  1. std::invoke (C++17)

      std::invoke(f1, 10);     // 일반 함수 호출
    std::invoke(f2, obj, 10); // 멤버 함수 호출
      
  2. std::mem_fn (C++11)

      auto f3 = std::mem_fn(&X::mf1);
    f3(obj, 10);  // 통일된 호출 방식
      

멤버 데이터 포인터

클래스의 특정 데이터 멤버를 가리키는 포인터입니다.

사용법

  class Point {
public:
    int x, y;
};

// 멤버 데이터 포인터 선언
int Point::*p2 = &Point::y;

// 사용 방법
Point pt;
pt.*p2 = 10;  // pt.y = 10과 동일

// C++17 이후 invoke 사용
std::invoke(p2, pt) = 20;  // pt.y = 20과 동일
  

저장 값

멤버 데이터 포인터는 C++ 표준에서 정확한 구현을 명시하지 않지만, 대부분의 컴파일러에서는 멤버 변수의 클래스 내 오프셋(offset)을 저장합니다. 이를 통해 실행 시간에 객체의 베이스 주소에 오프셋을 더해 실제 멤버의 주소를 계산할 수 있습니다.