c++如何实现一个Delegate c++委托机制【实例】

C++无内置委托类型,但可用std::function、lambda、bind等模拟类型安全可复制的单播与多播委托;示例涵盖基础封装、成员函数支持及多播实现,并强调生命周期管理与性能权衡。

C++ 本身没有内置的 Delegate(委托) 类型(不像 C#),但可以通过函数对象(std::function)、可调用对象(lambda、函数指针、绑定对象)和类型擦除等机制,模拟出**类型安全、可复制、支持多播(multicast)的委托行为**。下面是一个轻量、实用、可运行的 C++ 委托实现示例,支持单播与简单多播,不依赖第三方库。

1. 基础单播委托(Function Wrapper)

最常用且推荐的方式是使用 std::function 封装任意可调用对象,它本身就是一种“泛型委托”:

#include 
#include 

// 定义委托类型:接受 int,返回 void using IntHandler = std::function;

void OnValueChanged(int value) { std::cout << "Value changed to: " << value << '\n'; }

int main() { IntHandler handler = OnValueChanged; handler(42); // 输出:Value changed to: 42

// 也可绑定 lambda 或成员函数
handler = [](int x) { std::cout << "[Lambda] Got: " << x << '\n'; };
handler(100);

}

2. 手写轻量 Delegate 类(支持成员函数)

若需更明确的委托语义(如判空、重载 =、显式调用语法),可封装一个简易 Delegate 模板类。以下支持普通函数、lambda 和非静态成员函数(通过对象指针 + 成员函数指针):

#include 
#include 

template class Delegate;

template class Delegate { std::function fn_;

public: Delegate() = default; Delegate(std::nullptrt) {} Delegate(const std::function& f) : fn(f) {}

template
Delegate(F&& f) : fn_(std::forward(f)) {}

// 支持 obj->method 绑定(需传入对象指针)
template
Delegate(T* obj, M method) 
    : fn_(std::bind(method, obj, std::placeholders::_1...)) {}

bool operator==(std::nullptr_t) const { return !fn_; }
explicit operator bool() const { return static_cast(fn_); }
R operator()(Args... args) const { return fn_(std::forward(args)...); }

};

// 使用示例 struct Counter { int value = 0; void increment(int by) { value += by; } };

int main() { Counter c; Delegate del(&c, &Counter::increment); del(5); std::cout

3. 简易多播委托(MulticastDelegate)

多播委托 = 可添加/移除多个监听器,调用时依次执行。用 std::vector<:function> 实现最直观:

#include 
#include 
#include 

template class MulticastDelegate;

template class MulticastDelegate { std::vector> handlers_;

public: void add(const std::function& fn) { if (fn) handlers_.push_back(fn); }

void remove(const std::function& fn) {
    handlers_.erase(
        std::remove_if(handlers_.begin(), handlers_.end(),
            [&fn](const auto& h) { return h.target_type() == fn.target_type(); }),
        handlers_.end()
    );
}

void invoke(Args... args) const {
    for (const auto& h : handlers_) {
        h(std::forward(args)...);
    }
}

// 重载 () 直接调用
void operator()(Args... args) const { invoke(std::forward(args)...); }

};

// 示例:事件通知 int main() { MulticastDelegate onChanged; onChanged.add([](int v) { std::cout

onChanged(123); // 同时触发两个回调

}

4. 注意事项与建议

  • 生命周期管理是关键:绑定成员函数时,确保对象(如 &c)在委托调用前未被销毁;建议配合 std::shared_ptr 或 weak_ptr 防悬挂指针。
  • 性能考虑std::function 有小开销(类型擦除 + 可能堆分配),高频调用场景可用函数指针 + void* 手动绑定(但丧失类型安全)。
  • 不推荐手动实现“C# 式完整委托系统”:C++ 生态已有成熟方案,如 libdelegate、ENTT 的 signal,或 Boost.Signals2。
  • 现代替代思路:对事件驱动逻辑,优先考虑基于回调的观察者模式、信号槽(如 Qt)或协程+channel(C++20+)。