미리보기 :
// Function Pointer
/////////////////////////////// case1
typedef void (HELLO)(void); // 시그니처 : void (void)
HELLO* fn = &PrintHello;
(*fn)();
/////////////////////////////// case2
typedef void(*PHELLO)(void);
PHELLO pfn = &PrintHello;
(*pfn)();
/////////////////////////////// case3
void (*HELLO2)(void);
HELLO2 = &PrintHello;
HELLO2();
/////////////////////////////// case4
using HELLO3 = void(void);
HELLO3* fn2 = &PrintHello;
(*fn2)();
///////////////////////////////
함수에도 포인터가..? :
변수와 배열을 포인터로 가리킬 수 있듯이 함수도 포인터로 가리킬 수 있다.
함수 포인터는 말 그대로 함수를 가리킬 수 있는 포인터를 의미한다.
함수에도 주소가 있는가? -> 있다.
함수의 이름은 함수의 시작 주소를 가리킨다. (배열과 유사)
#include <iostream>
int sum(int a, int b) { return a + b; }
int main()
{
std::cout << "함수 sum의 주소 : " << &sum << std::endl;
}
함수 포인터 형태 :
typedef [반환형][이름]([인자])
// ex
int Add(int a, int b) { return a + b; } // 시그니처 : int(int, int)
typedef int ADD_FUNC(int, int); // 함수 포인터에 대한 타입에 이름 정의
ADD_FUNC* fn = Add; // 함수포인터 타입 변수(fn) 선언 정의
int num1 = (*fn)(1,2); // 3
int num2 = fn(1,2); // '*' 생략가능
함수 포인터 한번에 선언 :
자주 사용되는 방식이니 익숙해지도록 하자
int Test(int a, int b) { return a + b; }
int (*fn)(int, int); // 함수 포인터 타입에 대한 이름 설정 없이 한번에 함수 포인터 변수(fn) 선언
fn = &Test; // '&' 생략 가능
Modern C++ 방식 (using) :
int Test(int a, int b) { return a + b; }
using FUNC_TEST2 = int(int, int);
FUNC_TEST2* fn3 = Test;
int v1 = fn3(3, 4); // 7
int v2 = (*fn3)(3, 4); // 7
멤버 함수의 함수 포인터 :
지금까지의 함수 포인터 재정의 문법은 정적(static) / 전역 함수에만 적용할 수 있는 문법이었다.
멤버 함수에 대한 함수 포인터 재정의 문법은 살짝 다르다.
class Knight
{
public:
int GetHp()
{
std::cout << "GetHp : " << std::endl;
return Hp;
}
public:
int Hp;
};
int main()
{
typedef int(Knight::*PMEMFUN)();
PMEMFUN pmfn = &Knight::GetHp; // '&' 없으면 "비표준 구문" 에러 발생
Knight k1;
k1.GetHp();
(k1.*pmfn)(); // 복잡하다..
}
정적/전역 함수의 경우 "&" 연산자를 생략할 수 있지만, 멤버 함수의 경우 반드시 "&" 를 반드시 붙여줘야한다.
헷갈리니깐 그냥 생략하지 않도록 하자...
클래스의 멤버 함수는 어떤 특정객체를 대상으로 호출해야한다. 때문에 반드시 특정 객체가 존재해야한다.
정적/전역 함수의 경우 함수 포인터를 호출할 때 "*" 을 생략해도 됐지만, 멤버 함수의 경우 "*"을 생략하면 컴파일러 입장에서 k1 안의 pmfn 이라는 멤버 변수를 호출하는지 재정의된 멤버함수를 호출하는건지 헷갈리게된다.
이러한 이유 때문에 "*"을 생략할 수 없다.
이것도 헷갈리니... 그냥 생략하지 말자...ㅠ
객체가 포인터 타입인데 멤버 함수 포인터 타입을 호출하려는 경우 :
Knight* k2 = new Knight();
((*k2).*pmfn)(); // '*', '.' 은 '->'으로 대체 가능하다.
(k2->*pmfn)();
delete k2;
'DirectX11 > Rookiss' 카테고리의 다른 글
콜백 함수 (0) | 2024.03.16 |
---|---|
함수 객체 (Function Object) (0) | 2024.03.16 |
비트 연산 (0) | 2024.03.16 |
Modern C++_2 (0) | 2024.03.16 |
Mordern C++ (2) | 2024.03.15 |