본문 바로가기

C,C++

함수 포인터

간단 설명

일반 포인터와 같은 역할을 하고 있습니다.

일반 포인터는 변수가 하나 있다면 그 변수에 대한 메모리 주소 값을 가리키는 역할을 하고 있고

함수 포인터 또한 함수가 하나 있다면 그 함수에 대한 메모리 시작 주소 값을 가리키는 역할을 합니다.

 

 

 

 

사용 목적

일반적으로 저 같은 초보 개발자는 사용할 일이 거의 없다고는 하는데, 엔진에 대한 코드 분석이나 

콜백 함수를 사용할 때 원리에 대해 알고 있다면 도움이 된다고 하네요!

 

아래 문단의 예시 코드를 보면 

for (int i = 1; i <= count; ++i)
	{
		temp_sum = test_func_ptr(temp_sum, i);
	}

이러한 코드가 calculation()함수 안에 있는데,  간단한 더하기 빼기를 함수 포인터를 활용해 구현한 부분입니다.

만약에 함수 포인터를 사용하지않았더라면 이 calculation()에 직접적으로 adder와 remover를 때려박아야하는 일이 생길거에요.

(본인이 하드 코딩에 익숙하다면ㅠㅠ)

하지만 함수 포인터를 활용해서 위의 코드처럼 작성해둔다면 해당 인자 값만 맞춰서 나누기 곱하기 함수를 만들어서 

다시 수정할 필요도 없이 쓸 수 있기도 합니다.

아마 이런 장점 때문에 쓰지 않을까 싶어요.

 

 

 

 

방법

(반환 타입) (*함수명)(매개 변수 자료형)

void (*MyFunc)(void)

float (*MyFunc)(void)

void (*MyFunc)(int,int)

float (*MyFunc)(int, float)

...

 

 

 

 

예시 코드

#include <iostream>


int calculation(const int& sum_in, int count, int (*test_func_ptr) (const int&,const int&));

int adder(const int& sum_in, const int& value_in);
int remover(const int& sum_in,const int& value_in);


int main()
{

	std::cout << calculation(0, 10, adder);

	std::cout << calculation(0, 10, remover);

	return 0;
}


int calculation(const int& sum_in, int count, int (*test_func_ptr) (const int&,const int&))
{

	int temp_sum = sum_in;

	for (int i = 1; i <= count; ++i)
	{
		temp_sum = test_func_ptr(temp_sum, i);
	}

	return temp_sum;
	
}



int adder(const int& sum_in, const int& value_in)
{
	return sum_in + value_in;
}

int remover(const int& sum_in, const int& value_in)
{
	return sum_in - value_in;
}

 

 

예시코드 2

더보기
#include <iostream>
#include <string.h>

enum { ARRAY_SIZE = 10 };
enum { QUIT, NAME, AGE, TIER, MENU_COUNT };  // 0, 1, 2, 3, 4

class Character
{
public:
	Character() { name = "", age = 0, tier = 0; };
	Character(std::string name_in, int age_in, int tier_in) : name(name_in), age(age_in), tier(tier_in) {};
	~Character() {};


	Character operator = (Character& character_in)
	{

		name = character_in.name;
		age = character_in.age;
		tier = character_in.tier;

		return *this;
	}


public:
	std::string 		name;		//이름
	int			age;		//나이
	int			tier;		//티어

};


void init_characters(Character** characters_in, int size);
int select_menu();
void print_characters(Character* characters_in, int size);

int compare_name(const void* p1, const void* p2);
int compare_age(const void* p1, const void* p2);
int compare_tier(const void* p1, const void* p2);




int main()
{
	//함수 포인터 사용
	int (*compare_funcs[])(const void*, const void*) = { nullptr,compare_name, compare_age, compare_tier };
	Character* characters = nullptr;
	int select;

	init_characters(&characters, ARRAY_SIZE);

	std::cout << " [정렬 이전]" << std::endl;
	print_characters(characters, ARRAY_SIZE);

	while (true)
	{
		select = select_menu();

		if (select == QUIT)
			break;

		qsort(characters, ARRAY_SIZE, sizeof(characters[0]), compare_funcs[select]);	//선택의 값에 따라 해당 함수 호출
		print_characters(characters, ARRAY_SIZE);
	}

	return 0;
}


void init_characters(Character** characters_in, int size)	//더블 포인터를 써서 이 함수가 끝날 때쯤 값이 초기화 되는 것을 방지합니다.
{
	Character *data = new Character[10];

	Character id0("김미호", 29, 5);
	Character id1("조미주", 30,2);
	Character id2("구거녘", 26, 4);
	Character id3("큰슬기", 33, 2);
	Character id4("작슬기", 35, 3);
	Character id5("난기흥", 28, 1);
	Character id6("김민희", 29, 1);
	Character id7("죄민호", 32, 2);
	Character id8("하루히", 34, 1);
	Character id9("아이유", 30, 1);

	data[0] = id0;
	data[1] = id1;
	data[2] = id2;
	data[3] = id3;
	data[4] = id4;
	data[5] = id5;
	data[6] = id6;
	data[7] = id7;
	data[8] = id8;
	data[9] = id9;

	*characters_in = data;
	data = nullptr;
}

int select_menu()
{
	std::string menu;
	int index = -1;

	do
	{
		std::cout << "[메뉴] quit name age tier - ";
		std::cin >> menu;

		if (menu == "quit")
			index = QUIT;
		else if (menu == "name")
			index = NAME;
		else if (menu == "age")
			index = AGE;
		else if (menu == "tier")
			index = TIER;

	} while (index < 0 || index >= MENU_COUNT);

	return index;
}

void print_characters(Character* characters_in, int size)
{
	for (int i = 0; i < size; ++i)
	{
		std::cout << characters_in[i].name << " , " << characters_in[i].age << " , " << characters_in[i].tier << std::endl;
	}
}

int compare_name(const void* p1, const void* p2)
{
	Character* pb1 = (Character*)p1;
	Character * pb2 = (Character*)p2;

	return pb1->name > pb2->name;			//std::string은 사전순으로 빠른 순을 비교할 때 이렇게 합니다.
}

int compare_age(const void* p1, const void* p2)
{
	return ((Character*)p1)->age - ((Character*)p2)->age;		//나이 - 나이를 해서 음수라면 전자가 빠름 , 양수라면 후자가 빠름
}

int compare_tier(const void* p1, const void* p2)
{
	return ((Character*)p1)->tier - ((Character*)p2)->tier;		//나이와 같은 방식
}

 

함수포인터를 활용해 퀵소트를 다양한 조건으로 활용해본 코드입니다.

이것까진 안보셔도 될거에요!

예시코드 3

더보기
#include <iostream>
#include <map>


int melee_weapon(int a, int b) { return a + b; }
int gun_weapon(int a, int b) { return a * b; }
int magic_weapon(int a, int b) { return a*2 + b*2; }


int main()
{
	std::map<std::string, int (*)(int, int)> func_map =
	{ {"장검", melee_weapon},
		{"단검", melee_weapon},
		{"M4A1", gun_weapon},
		{"스태프", magic_weapon}
	};

	while (true)
	{
		std::string weapon;
		std::cout << "사용할 무기를 지정해 주세요." << std::flush;
		std::cin >> weapon;

		if (func_map.find(weapon) != func_map.end())
		{
			int a, b;
			std::cout << "최소 대미지, 최대 대미지를 입력해 주세요." << std::flush;
			std::cin >> a >> b;
			std::cout << weapon << "의 최종 대미지" << " = ";
			std::cout << func_map[weapon](a, b) << std::endl;
		}
		else
		{
			std::cout << " 해당 무기가 없습니다. " << std::endl;
		}
	}

	return 0;
}

함수포인터를 활용하여 이런 느낌으로 게임상에서 무기를 바꾼다거나 할 수도 있을 듯 합니다.

'C,C++' 카테고리의 다른 글

공부하면서 빠트린 것들 끄적끄적 - 얕은 복사 vs 깊은 복사  (0) 2023.09.25
함수 객체  (0) 2022.11.03
함수 템플릿  (0) 2022.11.01
클래스 템플릿  (0) 2022.11.01