함수 포인터

namu·2024년 3월 26일

int a;

typedef int DATA;

// 1) 포인터       *
// 2) 변수 이름    pointer
// 3) 데이터 타입  int
DATA* pointer = &a;

// 함수
typedef int(FUNC_TYPE)(int a, int b);
// using FUNC_TYPE = int(int a, int b);

// 1) 포인터       *
// 2) 변수 이름    fn
// 3) 데이터 타입  함수 (인자는 int, int 반환은 int)
FUNC_TYPE* fn;

// 함수의 이름은 함수의 시작 주소 (배열과 유사)
int result = Add(1, 2);
// push 2
// push 1
// call Add(0x.....)
// jmp 0x.....
cout << result << endl;

fn = Add;

result = fn(1, 2); // 기본 문법

result = (*fn)(1, 2); // 함수 포인터는 *(접근 연산자) 붙어도 함수 주소!

Item items[10] = {};
items[3]._rarity = 2; // RARE
Item* rareItem = FindItem(items, 10, IsRareItem);
bool IsRareItem(Item* item)
{
	return item->_rarity >= 2;
}

// 단점은 다음과 같이 인자가 달라지는 경우
bool IsOwnerItem(Item* item, int ownerId)
{
	return item->_ownerId == ownerId;
}

typedef bool(ITEM_SELECTOR)(Item* item);

Item* FindItem(Item items[], int itemCount, ITEM_SELECTOR* selector)
//Item* FindItem(Item items[], int itemCount, bool(*selector)(Item* item))
{
	for (int i = 0; i < itemCount; i++)
    {
    	Item* item = &items[i];
        if (selector(item))
        {
        	return item;
        }
    }
    
    return nullptr;
}
int Test(int a, int b)
{
	cout << "Test" << endl;
    return a + b;
}


// 함수 포인터
// 1) 포인터        *
// 2) 변수의 이름    fn
// 3) 타입          함수(인자로 int 2개를 받고, int 1개를 반환)

int (*fn)(int, int);

//typedef int(FUNC_TYPE)(int, int);
//FUNC_TYPE* fn;

fn = Test; // & 생략 가능 (C언어와의 호환성 때문)
fn = &Test;

fn(1, 2);

(*fn)(1, 2);

return 0;
// typedef 의 진실
// typedef 왼쪽 오른값 -> 오른쪽 (커스텀 타입 정의)
// 정확히는 왼쪽/오른쪽 기준이 아니라,
// [선언 문법]에서 typedef 을 앞에다 붙이는 쪽

typedef int INTEGER;
typedef int* POINTER;
typedef int FUNC(int, int);
typedef int ARRAY[20];

typedef int(*PFUNC)(int, int);

//FUNC* fn;
PFUNC fn;

// 위 문법으로 [전역 함수 / 정적 함수]만 담을 수 있다 (호출 규약이 동일한 애들)

class Knight
{
public:
	static void HelloKnight()
    {
    
    }

	// 멤버 함수
	int GetHp()
    {
    	cout << "GetHp()" << endl;
        return _hp;
    }
   
public:
	int _hp = 100;
};


Test(1, 2);

Knight k1;
k1.GetHp(1, 1);
// lea ecx, [k1] 자신을 ecx 레지스터에 넣은 다음,
// call Knight::GetHp (0F6143Dh) 호출

typedef int(Knight::*PMEMFUNC)(int, int); // 멤버 함수 포인터

PMEMFUNC mfn;
mfn = &Knight::GetHp;
// C언어 호환성 때문에 & 생략 가능했는데, 멤버 함수는 & 붙여야 됨.

(k1.*mfn)(1, 1); // k1 의 멤버와 구분을 위해 *을 꼭 붙인다?

Knight* k2 = new Knight();
((*k2).*mfn)(1, 1);
(k2->*mfn)(1, 1);

delete k2;
profile
안녕하세요

0개의 댓글