함수 포인터
함수 포인터
- 함수의 메모리 주소를 값으로 가지는 포인터 변수.
- 함수 포인터를 사용하면, 함수를 변수처럼 사용할 수 있음.
- 함수의 메모리는 "CODE" 메모리 영역에 저장되어 있으며, 함수 포인터를 따라가면 "CODE" 메모리 영역에 있는 해당 함수의 내용이 들어있음.
- 문법 : 함수 반환 자료형(함수 포인터 이름)(함수 매개 변수 자료형, ...) = 함수 이름
Ex) int(fp)(int, int) = Print;
멤버 함수 포인터
- 기존 함수 포인터는 전역 함수 및 정적 함수만 사용 가능.
- 멤버 함수 포인터는 전역 함수 및 정적 함수와 함수 호출 규약이 다르기 때문에 문법이 다름.
- 문법 : 함수 반환 자료형(클래스::*멤버 함수 포인터 이름)(함수 매개 변수 자료형, ...) = &멤버 함수 이름
- '&' 기호를 꼭 붙여줘야 되는 것에 주의.
Ex) int(Player::*mfp)(int, int) = &Player::PrintID;
함수 호출 규약
1. __cdecl
- 전역 함수, 정적 함수의 함수 호출 규약.
- 스택 메모리 정리 주체 = 함수 호출자. (main() 에서 printf() 호출시 main()이 함수 호출자)
- 호출자가 피호출자 함수의 매개 변수 정보를 알고 있기 때문에, 가변 인자 사용 가능.
2. __thiscall
- 멤버 함수의 함수 호출 규약.
- 가변 인자를 사용하지 않는 멤버 함수에서 사용.
- 자신이 속한 객체를 가리키는 this 포인터를 추가로 가지고 있음. (숨겨져 있음)
구현
#include <iostream>
using namespace std;
int Add(int a, int b)
{
cout << "Add() 호출" << endl;
return a + b;
}
class Player
{
public:
Player(int pid) : _pid(pid) { }
void PrintID()
{
cout << "PrintID() 호출 : " << _pid << endl;
}
public:
int _pid;
};
int main()
{
int(*fp)(int, int) = Add;
fp(1, 2);
void(Player::*mfp)() = &Player::PrintID;
Player* p = new Player(1);
(p->*mfp)();
delete p;
}
함수 객체 (Functor)
- 함수처럼 동작하는 객체.
- '()' 연산자 오버로딩 필요.
- 추후 서버쪽에서 커맨드 패턴으로 활용.
#include <iostream>
using namespace std;
class Functor
{
public:
void operator()()
{
cout << "Functor Test" << endl;
cout << "Value = " << _value << endl;
}
void operator()(int n)
{
cout << "Functor Test" << endl;
cout << "Value = " << n << endl;
}
public:
int _value = 0;
};
int main()
{
Functor functor;
functor();
functor(314);
}