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

发布时间 - 2026-01-03 00:00:00    点击率:
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+)。


# go  # app  # ai  # c++  # ios  # stream  # c#  # red  # gate  # qt  # 封装  # 成员函数  # int  # void  # Lambda  # 指针  #   # signal  # Struct  # Delegate  # 委托  # 泛型  # channel  # function  # 对象  # 事件  # ui  # 绑定  # 回调  # 是一个  # 擦除  # 多个  # 已有  # 也可  # 可以通过  # 不像  # 第三方 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制  如何快速启动建站代理加盟业务?  打开php文件提示内存不足_怎么调整php内存限制【解决方案】  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程  Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  高防服务器租用首荐平台,企业级优惠套餐快速部署  黑客如何通过漏洞一步步攻陷网站服务器?  如何用PHP快速搭建CMS系统?  利用python获取某年中每个月的第一天和最后一天  Edge浏览器如何截图和滚动截图_微软Edge网页捕获功能使用教程【技巧】  中山网站推广排名,中山信息港登录入口?  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  历史网站制作软件,华为如何找回被删除的网站?  Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解  Laravel如何生成API文档?(Swagger/OpenAPI教程)  高端网站建设与定制开发一站式解决方案 中企动力  Android滚轮选择时间控件使用详解  详解jQuery中的事件  如何用狗爹虚拟主机快速搭建网站?  Laravel怎么使用Session存储数据_Laravel会话管理与自定义驱动配置【详解】  Laravel storage目录权限问题_Laravel文件写入权限设置  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  高端智能建站公司优选:品牌定制与SEO优化一站式服务  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  香港服务器网站卡顿?如何解决网络延迟与负载问题?  Python正则表达式进阶教程_复杂匹配与分组替换解析  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程  googleplay官方入口在哪里_Google Play官方商店快速入口指南  移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?  Android自定义listview布局实现上拉加载下拉刷新功能  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  如何快速搭建虚拟主机网站?新手必看指南  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  如何将凡科建站内容保存为本地文件?  Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面  Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性  javascript基于原型链的继承及call和apply函数用法分析  清除minerd进程的简单方法  零基础网站服务器架设实战:轻量应用与域名解析配置指南  网站制作免费,什么网站能看正片电影?  jquery插件bootstrapValidator表单验证详解  MySQL查询结果复制到新表的方法(更新、插入)