함수 포인터를 알기 전에 포인터에 대해 알고가자
포인터 : 주소를 저장하는 메모리 공간 이름
함수 포인터 : 함수의 시작주소를 저장하는 포인터
-> 함수의 이름은 함수가 시작하는 시작 주소
-> ex)
void Print (int n) { } // 함수
void (*pf) (int); // 함수 포인터
pf = Print; // 함수 포인터에 함수의 시작주소 저장
함수 포인터 : 반환형타입 (*함수포인터 이름) (매개변수)
클래스 객체와 관계없이 호출이 가능한 포인터이다
-> 어떤 객체를 가리킬 지 신경 쓸 필요가 없다
정적 함수 포인터는 주로 전역함수, 클래스 내부 static 멤버 함수 호출에 사용된다
근데 정적 멤버 함수 자체는 정적 함수 포인터를 사용하지 않더라도 객체없이 바로 접근이 가능함
-> 굳이 사용하지 않아도 되지만, 포인터 배열을 사용하거나 런타임 중 동적으로 정적 멤버 함수를 선택하고 싶을땐 사용
전역함수 Print(int n)와 멤버함수 Print(int n)를 생성
메인함수에 정적 함수 포인터 선언 void (*ptr)(int)
-> 반환형(void) (*포인터 이름) (매개변수 타입&갯수)
#include <iostream>
using namespace std;
void Print(int n)
{
cout << "전역 함수 : " << n << endl;
}
class Point
{
public:
static void Print(int n)
{
cout << "Point 클래스의 정적 멤버 변수 : " << n << endl;
}
};
int main()
{
void (*ptr)(int); // 정적 함수 포인터 선언
ptr = Print; // 포인터에 함수 이름(주소) 저장
ptr(10); // 전역 함수 호출
ptr = Point::Print;
ptr(10); // 정적 멤버 함수 호출
}
ex) MyClass 타입의 객체를 생성하지 않아도 MyClass:: 함수 이름으로 호출이 가능하다

반환형타입 (호출할 클래스::*함수포인터 이름) (매개변수)
-> 멤버 함수 포인터 선언 자체는 동일하게 하지만, 함수의 호출방법은 서로 다르다

MyClass클래스 안의 멤버 함수인 memberFunction 함수를 호출하고 싶다
멤버 함수 포인터 생성
-> void (MyClass:: * ptr)();
포인터에 내가 호출하고자 하는 멤버함수의 주소값을 저장한다
-> ptr = &MyClass::memberFunction;
포인터 생성하고 값을 초기화 하는 과정을 한번에 적어도 상관없다 (나는 가독성을 위해 따로 적었다)
->void (MyClass::*ptr)() = &MyClass::memberFunction;
(객체.*포인터이름)(매개변수); 로 호출(obj.*ptr)();#include <iostream>
using namespace std;
class MyClass
{
public:
void memberFunction()
{
cout << "멤버함수 호출(콜)! " << endl;
}
};
int main()
{
MyClass obj;
void (MyClass:: * ptr)();
ptr = &MyClass::memberFunction;
(obj.*ptr)();
}
void (MyClass:: * ptr)();ptr = &MyClass::memberFunction;-> ptr은 MyClass 클래스의void memberFunction()을 가리킬 수 있는 포인터
주소로 멤버 함수를 호출하는 방법은 포인터를 사용한 것이다
-> MyClass 타입의 객체 obj를 만들고, 이 객체의 주소값을 가리킬 *p를 생성한다
*p는 MyClass 객체의 주소값을 가리키고 있기 때문에, p를 이용하여 멤버 함수 포인터에 접근하여 함수 호출이 가능하다
-> (p -> *ptr)();
-> p->*ptr은 p 포인터가 가리키는 객체에서 ptr이 가리키는 멤버 함수를 호출하는 방식

근데 내가 보기엔 객체를 사용하여 바로 포인터를 호출하는 게 더 효율적인 거 같다
-> 굳이 객체의 주소를 가리키는 포인터를 만들고 그 주소에서 ptr이 가리키는 함수를 호출하는 건 두번 일하는 거 아닐까 싶다 (심지어 성능차이도 없음)
#include <iostream>
using namespace std;
class MyClass
{
public:
void memberFunction()
{
cout << "멤버함수 호출(콜)! " << endl;
}
};
int main()
{
MyClass obj;
MyClass *p = &obj;
void (MyClass:: * ptr)();
ptr = &MyClass::memberFunction;
(p->*ptr)();
}

MyClass::memberFunction();)
MyClass클래스의 obj객체를 생성하고, 객체를 사용하여 멤버 함수(memberFunction)를 호출함동적으로 함수 호출이 가능하다
어떤 조건에 따라 다르게 처리하고 싶은 경우에 사용한다
#include <iostream>
using namespace std;
class MyClass
{
public:
void FunctionA()
{
cout << "멤버함수 A호출(콜)! " << endl;
}
void FunctionB()
{
cout << "멤버함수 B호출(콜)! " << endl;
}
};
int main()
{
MyClass obj;
void (MyClass:: * ptr)();
ptr = &MyClass::FunctionA;
(obj.*ptr)();
ptr = &MyClass::FunctionB;
(obj.*ptr)();
return 0;
}
멤버함수 FunctionA와 FunctionB가 있는데 프로그램을 실행하면(런타임), 멤버 함수 포인터에 동적으로 주소값이 저장된다
-> 프로그램 시작 전까지는 멤버 함수 포인터가 선언만 된 상태 (주소값 할당 전)
여러개의 멤버 함수가 있고, 런타임 중에 결정되야 한다면 멤버 함수 포인터를 사용하는 게 좋겠죠
