나만의 작은 도서관

[C++][Callback] #3. 함수 객체(functor) 본문

C++/문법 및 메소드(STL)

[C++][Callback] #3. 함수 객체(functor)

pledge24 2025. 4. 3. 00:16

함수 객체(functor)란?

class Functor 
{
public:
    void operator()() { /* do something */ }
}

Functor functor;
functor(); // = functor.operator() 함수 호출
  • functor는 callable 한 개체 중 하나로, 호출 연산자 ()를 오버로딩하여 함수처럼 사용할 수 있는 객체를 의미한다.
  • functor는 C++ 전반적으로 자주 활용되며, 대표적으로 STL에서 자주 활용되어 있다.

 

functor 예제

#include <iostream>

using namespace std;

class Functor
{
public:
    void operator()() { cout << "Functor Calling: " << _value << '\\n'; }

private:
    int _value = 10; // 상태 데이터
};

int main()
{
    Functor functor;
    // Functor functor(); 는 함수 전방 선언이므로, functor는 객체 생성 후에 호출해야한다.
    functor(); // 실행 결과: Functor Calling: 10

    return 0;
}

Functor의 활용 예제

1. 커맨드 패턴

  • 커맨드 패턴작업을 객체로 캡슐화하여 큐에 저장하거나 취소하는 등, 작업의 실행 시점을 컨트롤하는 디자인 패턴을 의미한다.
  • Functor는 커맨드 패턴에서 작업을 객체로 캡슐화할 때 활용할 수 있다.

 

2. 클로저(Closure)로서의 활용

  • functor를 사용하면 상태를 가진 함수, 클로저를 만들 수 있다.
  • static 함수도 상태를 저장할 수 있지만, functor는 static 함수와 달리 각 객체마다 독립적인 상태를 가질 수 있기 때문에 서로 다른 상태를 가진 여러 클로저를 동시에 유지하면서 동작시킬 수 있다.

 

JobQueue+클로저 활용 예제(MMORPG 이동 패킷처리 의사? 코드)

queue<MoveJob> jobQueue; // 작업(Job)을 저장하는 큐

/* Functor */
class MoveJob
{
public:
    MoveJob(int characterId, int newX, int newY)
        : characterId(characterId), x(newX), y(newY) {}

    void operator()() { processMoveJob(); }

private:
    int characterId; // 상태값 저장(클로저)
    int x, y;
};

/* 작업 추가 역할 */
void Producer()
{
    while (true)
    {
        int id, x, y;
        /* 수신된 네트워크 패킷 중, 이동 패킷을 작업(Job)으로 변환... */

        // 이동 작업을 Functor로 생성하여 큐에 추가
        jobQueue.push(MoveJob(id, x, y));
    }
};

/* 작업 소비 역할 */
void Consumer()
{
    while (!jobQueue.empty())
    {
        auto job = jobQueue.front();
        jobQueue.pop();
        job(); // 실행
    }
}

std::thread producerThread(Producer); // Job 생성 전용 쓰레드
std::thread consumerThread(Consumer); // Job 실행 전용 쓰레드

producerThread.join();
consumerThread.join();

 

 

3. STL 알고리즘 헤더 함수

  • STL 알고리즘 헤더에 포함된 함수들은(std::sort()와 같이) 사용자가 원하는 방식으로 동작하기 위해 사용자가 정의한 함수를 class 타입의 인자로 받는다. 이때 functor는 “객체”이므로, 정의한 functor를 인자로 넘겨줄 수 있다.
// 비교 Functor 정의
struct CompareDescending {
    bool operator()(int a, int b) const {
        return a > b;  // 내림차순 정렬
    }
};

std::vector<int> vec = {5, 2, 8, 1, 3};

// Functor 객체를 전달하여 정렬 기준을 내림차순으로 변경
std::sort(vec.begin(), vec.end(), CompareDescending()/*이름없는 Functor*/);

 


참고 자료

https://www.cs.fsu.edu/~myers/cop3330/notes/functors.html

https://pangtrue.tistory.com/19

https://0xd00d00.github.io/2023/03/31/ecourse_basic_21_operator_overloading_0.html