[함수 포인터] 02. 콜백 함수와 델리게이트
콜백 함수(Callback function)와 델리게이트(Delegate)는 프로그램의 유연성과 확장성을 증가시켜주는 고급 프로그래밍 기법입니다.
프로그래밍을 하다 보면 종종 다양한 상황에 맞추어 동작을 변경해야 할 때가 있습니다. 이러한 상황에서 콜백 함수와 델리게이트는 다양한 상황에서 동작을 변경시켜 주면서도 디커플링을 유지시켜주는, 매우 유연한 프로그래밍을 가능하게 하는 강력한 도구입니다.
미리 설명하면, 콜백 함수는 다른 함수를 호출할 때 그 함수를 인자로 전달하고, 이후에 해당 함수를 호출하는 방식으로 동작합니다.
델리게이트는 객체 지향 프로그래밍 언어에서 흔히 사용되는 개념으로, 함수를 변수처럼 다룰 수 있게 해줍니다.
콜백 함수(Callback function)
함수 포인터의 유용한 기능 중 하나는 함수를 다른 함수에 전달할 수 있다는 점입니다.
이때, 다른 함수에 인자로 전달되어 특정 이벤트나 조건이 발생했을 때 호출되는 함수를 콜백 함수라고 합니다.
이러한 방식은 비동기 처리, 이벤트 리스닝, 사용자 정의 동작 수행 등 다양한 상황에서 사용될 수 있습니다.
콜백 함수의 장단점
- 장점
- 유연성: 콜백 함수를 사용하면 함수의 동작을 동적으로 변경할 수 있어 프로그램이 더 유연해집니다.
- 재사용성: 특정 작업을 수행하는 콜백 함수를 여러 곳에서 재사용할 수 있습니다.
- 단점
- 복잡성: 콜백 함수를 과도하게 사용하면 코드의 복잡성이 증가할 수 있습니다.
델리게이션(Delegation)과 델리게이트(Delegate)
델리게이션(Delegation)이란, 작업을 다른 사람에게 분배하고 위임하는 과정을 말합니다.
따라서, 프로그래밍에서 델리게이션 패턴은 객체 지향 프로그래밍에서 한 객체가 자신의 일부 기능을 다른 객체에 위임하는 것을 의미합니다. 이는 결합도를 낮추고 유연성을 증가시키기 위해 사용됩니다.
특히, 델리게이트(Delegate)는 C#과 같은 언어에서 사용되는 개념으로, 함수 포인터에 대응하는 개념입니다.
델리게이트를 사용하여 메서드(함수)를 변수에 할당하고, 이를 통해 메서드를 간접적으로 호출할 수 있습니다.
델리게이트의 특징
- 유연성: 실행 시점에 이벤트 처리 할 함수를 변경함으로써, 동작을 유연하게 변경할 수 있습니다.
- 이벤트 처리: 델리게이트는 이벤트 기반 프로그래밍에서 이벤트 핸들러로 사용할 수 있습니다.
- 콜백 함수: 델리게이트는 콜백 함수의 매개변수로도 사용할 수 있습니다.
- 멀티 캐스팅: 델리게이트는 C++의 함수 포인터와는 달리 1:N 관계, 즉 멀티캐스팅(multicasting)을 지원합니다.
즉, 델리게이트는 C++의 함수 포인터의 기능 뿐만 아니라, 이를 관리하고 1:N으로 호출하는 기능을 포함하는 객체입니다.
C++로 델리게이트 구현
C++로 델리게이트와 비슷한 기능을 가진 객체를 생성하고 호출하는 코드를 작성 해보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <vector>
class CustomDelegate
{
private:
using FuncType = void(*)();
std::vector<FuncType> delegates;
public:
void Bind(FuncType func)
{
delegates.push_back(func);
}
void Broadcast()
{
for (void(*&func)() : delegates)
{
func();
}
}
};
void func1()
{
std::cout << "func1" << '\n';
}
void func2()
{
std::cout << "func2" << '\n';
}
int main()
{
CustomDelegate customDelegate;
customDelegate.Bind(func1);
customDelegate.Bind(func2);
customDelegate.Broadcast();
}
델리게이트의 1:N 호출에 대응하기 위해, vector
로 함수 포인터들을 담는 배열을 하나 만들었습니다.
이때, 함수 포인터의 이름을 단순화 하기 위해 using을 사용했습니다.
(함수 포인터를 단순화하여 사용하는 글은 링크를 방문해 주세요.)
이후, Bind()
와 Broadcast()
로 함수 시그니처가 맞는 함수를 등록하거나 호출합니다.
일단, 이렇게만 구현해도 Unreal C++과 비슷하게 델리게이트 객체를 생성할 수 있었습니다.