함수 포인터

Jaemyeong Lee·2024년 10월 30일
0

1. 함수 포인터란?

🌟 정의: 함수를 가리키는 포인터

  • 함수 포인터는 함수의 메모리 주소를 저장하는 변수입니다.
  • 데이터 타입(int, double)처럼 함수도 메모리에 로드되며, 그 주소를 함수 포인터로 저장할 수 있습니다.

👍 장점: 실행 시점을 뒤로 미룰 수 있다

  • 함수를 가리키는 포인터를 사용하면 특정 함수를 호출할 시점을 프로그래머가 조정할 수 있습니다.
  • 이는 다양한 요청을 처리할 때 순서를 동적으로 제어할 수 있음을 의미합니다.

2. 함수 포인터의 기본 사용법

2-1. 함수 정의

void Print() {
    cout << "Hello World" << endl;
}

int Add(int a, int b) {
    return a + b;
}
  • Print 함수: 단순히 "Hello World"를 출력합니다.
  • Add 함수: 두 정수를 인자로 받아 합을 반환합니다.
  • 이 두 함수는 함수 포인터로 저장하여 호출 시점을 제어할 수 있습니다.

2-2. 함수 포인터 타입 정의

타입 정의 방식

  1. typedef 방식:
    typedef int(*FuncPtrType)(int, int);
    • FuncPtrType은 두 개의 int를 받아 int를 반환하는 함수 포인터의 별칭입니다.
  2. using 방식 (C++11 이상):
    using FuncPtrType = int(*)(int, int);
    • using은 현대적인 방식으로 코드 가독성을 높입니다.

2-3. 함수 포인터에 함수 저장

FuncPtrType func = &Add;
  • func 변수는 함수 포인터이며 Add 함수의 주소를 저장합니다.
  • 함수 포인터에 함수 주소를 저장할 때 & 연산자를 생략할 수도 있습니다:
    FuncPtrType func = Add;  // 동일

2-4. 함수 포인터로 함수 호출

int result = func(10, 20);  // Add 함수 호출
cout << result;  // 출력: 30
  • 함수 포인터를 통해 Add 함수가 호출됩니다.
  • 이는 함수 이름 대신 포인터 변수를 통해 호출하는 것입니다.

3. 함수 포인터 활용 예제

3-1. 콜백 함수

콜백 함수는 특정 이벤트가 발생할 때 호출되는 함수를 의미하며, 함수 포인터로 구현됩니다.

DoSomething 함수

int DoSomething(int a, int b, FuncPtrType func) {
    return func(a, b);  // func 호출
}
  • DoSomething 함수는 두 정수를 인자로 받고, 함수 포인터 func를 통해 계산합니다.

사용 예

int result = DoSomething(10, 20, Add);
cout << result;  // 출력: 30
  • DoSomethingAdd를 함수 포인터로 받아 호출합니다.

3-2. 아이템 검색 예제

Item 클래스

class Item {
public:
    int _itemId = 0;
    int _rarity = 0;
    int _ownerId = 0;
};
  • Item은 아이템의 ID, 희귀도, 소유자 ID를 저장하는 클래스입니다.

함수 포인터를 이용한 검색

using ItemSelectorType = bool(*)(Item* item);

Item* FindItem(Item items[], int itemCount, ItemSelectorType selector) {
    for (int i = 0; i < itemCount; i++) {
        if (selector(&items[i])) {
            return &items[i];
        }
    }
    return nullptr;
}
  • ItemSelectorType: Item 포인터를 매개변수로 받아 bool을 반환하는 함수 포인터 타입입니다.
  • FindItem: 배열의 아이템 중 selector 조건을 만족하는 첫 번째 아이템을 찾습니다.

사용 예

bool IsRare(Item* item) {
    return item->_rarity == 1;  // 희귀도 체크
}

Item items[10];
Item* rareItem = FindItem(items, 10, IsRare);
  • IsRare 함수는 희귀도가 1인 아이템을 찾는 조건입니다.

4. 멤버 함수 포인터

4-1. 정의

class Test {
public:
    void PrintTest() {
        cout << "Test function called" << endl;
    }
};
  • PrintTestTest 클래스의 멤버 함수입니다.

4-2. 멤버 함수 포인터 타입

using MemFuncPtrType = void(Test::*)();
  • MemFuncPtrType: Test 클래스의 멤버 함수 포인터 타입입니다.
  • void(Test::*)(): Test 클래스 멤버 함수 중 반환형 void이고 인자가 없는 함수 포인터 타입입니다.

4-3. 멤버 함수 호출

Test t;
MemFuncPtrType funcPtr = &Test::PrintTest;  // 포인터 초기화
(t.*funcPtr)();  // 호출: 객체와 함께 사용
  • funcPtr: PrintTest 멤버 함수를 가리킵니다.
  • 호출 방식:
    • 객체와 함께 .* 연산자로 호출: (t.*funcPtr)()
    • 포인터 객체일 경우 ->* 연산자 사용: (t2->*funcPtr)().

5. 함수 포인터의 한계

  1. 타입 안정성 부족: 함수 시그니처가 잘못될 경우 런타임 오류 발생 가능.
  2. 가독성 저하: 포인터 사용으로 코드가 복잡해질 수 있음.
  3. 호출 오버헤드: 포인터를 통한 간접 호출은 직접 호출보다 느림.
  4. 제한된 최적화: 컴파일 타임에 함수 호출을 최적화할 기회가 제한됨.
  5. 포인터 연산 제한: 일부 환경에서는 함수 포인터 연산이 제한적임.

profile
李家네_공부방

0개의 댓글