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

8次阅读

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

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

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:" <

}

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)……); }

};

立即学习 C++ 免费学习笔记(深入)”;

// 使用示例 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)……); }

};

立即学习 C++ 免费学习笔记(深入)”;

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

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

}

4. 注意事项与建议

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

星耀云
版权声明:本站原创文章,由 星耀云 2026-01-03发表,共计441字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources