간단 설명
일반 포인터와 같은 역할을 하고 있습니다.
일반 포인터는 변수가 하나 있다면 그 변수에 대한 메모리 주소 값을 가리키는 역할을 하고 있고
함수 포인터 또한 함수가 하나 있다면 그 함수에 대한 메모리 시작 주소 값을 가리키는 역할을 합니다.
사용 목적
일반적으로 저 같은 초보 개발자는 사용할 일이 거의 없다고는 하는데, 엔진에 대한 코드 분석이나
콜백 함수를 사용할 때 원리에 대해 알고 있다면 도움이 된다고 하네요!
아래 문단의 예시 코드를 보면
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 |