2025. 4. 29. 18:06ㆍProgramming Language/C++
클래스의 멤버 함수 포인터는 일반 함수 포인터와는 다르게 어떤 객체의 멤버 함수인지를 가리킨다는 특징이 있다. 이는 객체 지향에서 객체마다 다른 this 포인터를 갖기 때문에 함수 호출 시 특별한 문법이 필요하기 때문이다.
1. 멤버 함수 포인터의 정의
멤버 함수 포인터의 기본적인 정의방법은 아래와 같다.
반환형 (클래스명::*포인터이름)(매개변수 목록);
이를 사용한 예시로는
class MyClass {
public:
void show(int a) {
std::cout << "Value: " << a << std::endl;
}
};
void (MyClass::*funcPtr)(int) = &MyClass::show;
와 같이 사용할 수 있다.
2. 멤버 함수 포인터의 사용
멤버 함수 포인터를 사용해서 함수를 호출할때에는 단순히 funcPtr(5) 이런 식으로는 호출할 수 없다.
왜냐면 멤버 함수 포인터의 경우는 무조건 this를 전달해줘야하는데 저렇게 그냥 호출하면 this가 뭔지 구체화할 수 없기 때문에 그 객체를 기준으로 호출해줘야만 하고 그 방법은 아래와 같다.
MyClass obj;
(obj.*funcPtr)(5); // 객체로 호출
보면 멤버 함수 포인터에는 직접적으로 구현된 무언가에 연결된 부분은 없고 그냥 어떤 클래스에 존재하는 함수를 포인터로 가리키겠다라는 정보만 있기 때문에 실제 구체적인 객체를 연결해줄때는 같은 클래스이기만 하면 연결이 가능하다.
또한 이를 포인터로 구현하는 경우는
MyClass obj;
MyClass* pObj = &obj;
(pObj->*funcPtr)(10);
이렇게 화살표 표기법을 사용해서 호출도 가능하다.
정리해보자면
1. funcPtr은 MyClass 클래스의 멤버 함수 show(int) 를 가리킴(void (MyClass::*funcPtr)(int) = &MyClass::show;)
2. 근데 C++에서는 멤버 함수 호출 시 내부적으로 this 포인터가 필요함
3. 그럼 어떤 객체의 this를 줄 건데
1) 바로 pObj가 obj를 가리키고 있으니까
2) pObj->*funcPtr이라고 해서, obj를 대상으로 멤버 함수 호출하는 것
결과적으로 funcPtr만으로는 show가 "누구의 show인지" 알 수 없고 pObj를 통해서 이 객체의 show를 호출하라 고 말하는 것임
3. 멤버 함수 포인터의 간편화
멤버 함수 포인터의 타입을 보면 매우 복잡하게 구현됨을 알 수 있는데 이를 간단하게 사용할 수 있는 방법은 우리가 이전에 사용했던 typedef, using, std::function이 있다.
1) typedef 사용
// typedef를 사용한 alias 정의
typedef 반환형 (클래스명:: * alias명)(메게변수타입);
// alias를 사용한 선언
alias명 변수명 = &클래스명::함수명;
그리고 이렇게 만든 멤버 함수 포인터의 사용은 기존의 멤버함수 포인터의 사용과 동일하다(객체 선언, 포인터 선언 등등으로 사용)
2) using의 사용
//using을 사용한 alias 정의
using alias명 = 반환형(클래스명::*)(반환타입);
//alias를 사용한 선언
alias명 변수명 = &클래스명::함수명;
그리고 이렇게 만든 멤버 함수 포인터의 사용은 기존의 멤버함수 포인터의 사용과 동일하다(객체 선언, 포인터 선언 등등으로 사용)
3) std::function의 사용
//기존의 std::function을 사용한 alias 정의
std::function <반환명(매개변수 타입)> 변수명 = 함수명;
// 멤버 함수 포인터를 위한 std::function
std::function <반환명(클래스명* ,매개변수 타입)> 변수명 = &클래스명::함수명;
=> this포인터의 타입을 매개변수 첫번째 인자로 전달한다고 생각하면 됨
std::function의 경우는 alias를 설정하는게 아니라 아예 선언을 하는 것이기 때문에 사용 방법도 달라진다.
기존엔
과 같이 사용했었는데 std::function을 사용하면
이렇게 사용해줘야 한다.
//멤버 함수 포인터의 기존 사용 방식
void (MyClass:: *funcPtr)(int) = &MyClass::show;
//객체 생성
MyClass myclass;
//멤버 함수 포인터를 통한 함수 접근
(myclass.*funcPtr)(10); // == myclass.show(10)
//std::function을 사용한 방식
std::function <void (MyClass*, int)> funcPtr = &MyClass::show;
//객체 생성
MyClass myclass;
//std::function방식을 사용한 멤버 함수 포인터를 통한 함수 접근
funcPtr(myclass*, 10); // == myclass.show(10)
3. static 멤버 함수 포인터의 사용
static 멤버 함수의 경우는 this를 넘겨줄 필요가 없기 때문에 일반 함수 포인터와 사용방법이 비슷하다.
이걸 볼때보면 멤버 함수 포인터의 명칭에 붙는 클래스:: 부분은 순수하게 this때문에 붙는거라고 인식할수 있다.
'Programming Language > C++' 카테고리의 다른 글
Part2::Ch 02. 연산자 오버로딩- 03. 비교&관계 연산자 오버로딩 (0) | 2025.05.02 |
---|---|
Part2::Ch 02. 연산자 오버로딩- 01&02. 산술 연산자 오버로딩 (0) | 2025.05.02 |
Part2::Ch 01. 클래스 - 08. 정적 멤버 (0) | 2025.04.29 |
Part2::Ch 01. 클래스 - 07. const (0) | 2025.04.29 |
Part2::Ch 01. 클래스 - 06. this 포인터 (0) | 2025.04.29 |