在GUI编程或者基于事件开发的项目中,经常需要使用回调函数. 为了处理这类回调事件, C# 特别提供了关键字delegate来实现.
在传统的C++开发过程中, 为了实现函数回调,一般的做法是将 C++ 的函数指针传给管理者.当有事件触发时,再执行该回调函数.
基于函数指针的回调方式有一下缺点:
为了解决此类问题, C++11 从boost库中借鉴了新特性 functional, 以此为容器存储函数指针,从而优雅的实现回调机制
案例演示:
- #pragma once
- #include
- #include
-
- void print_num(int i);
-
- inline void print_num(int i)
- {
- std::cout << i << '\n';
- }
-
- struct PrintNum {
- void operator()(int i) const
- {
- std::cout << i << '\n';
- }
- };
-
- struct Foo {
- Foo(int num) : num_(num) {}
- void print_add(int i) const { std::cout << num_ + i << '\n'; }
- int num_;
- };
-
- void main();
-
- inline void main()
- {
- // store a free function
- std::function<void(int)> f_display = print_num;
- f_display(-9);
-
- // store a lambda
- std::function<void()> f_display_42 = []() { print_num(42); };
- f_display_42();
-
- //store the result of a call to std::bind
- std::function<void()> f_display_31337 = std::bind(print_num, 31337);
- f_display_31337();
-
- // //store a call to a member function
- //std::function
f_add_display = &Foo::print_add; - const Foo foo(314159);
- //f_add_display(foo, 1);
-
- //store a call to a data member accessor
- //std::function
f_num = &Foo::num_; - //std::cout << "num_: " << f_num(foo) << '\n';
-
- // store a call to a member function and object
- using std::placeholders::_1;
- std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
- f_add_display2(2);
-
- // store a call to a member function and object ptr
- std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
- f_add_display3(3);
-
- // store a call to a function object
- std::function<void(int)> f_display_obj = PrintNum();
- f_display_obj(18);
- }
- #pragma once
- #include
- #include
- #include
-
- using namespace std;
- class IObj
- {
- public:
- virtual int callback(string t_data) = 0;
- };
-
-
- class AppleObj : public IObj
- {
-
- public:
- virtual int callback(string t_data) final
- {
- cout << "this is appleobj : " << endl;
- return 0;
- }
- };
-
- class BananaObj : public IObj
- {
- public:
- virtual int callback(string t_data) final
- {
- cout << "this is banana object: " << endl;
- return 1;
- }
- };
-
-
- class DeleManager
- {
- public:
- DeleManager() {};
- ~DeleManager() {};
- void addObj(function<int(string)> t_dele)
- {
- _dele_list.push_back(t_dele);
- }
- void notify(string t_msg)
- {
- if (_dele_list.empty())
- {
- cout << "list is empty " << endl;
- return;
- }
-
- for (auto itor : _dele_list)
- {
- itor(t_msg);
- }
- }
-
- private:
- vector
int(string)>> _dele_list; - };
-
- void main()
- {
- DeleManager i_manager;
- AppleObj i_apple;
- BananaObj i_banana;
- using std::placeholders::_1;
- std::function<int(string)> i_dele_apple = std::bind(&AppleObj::callback, i_apple, _1);
- i_manager.addObj(i_dele_apple);
- std::function<int(string)> i_dele_banana = std::bind(&BananaObj::callback, i_banana, _1);
- i_manager.addObj(i_dele_banana);
- i_manager.notify("happy middle september day");
- }
在windows GUI 开发过程中, 一般通过 postmessage 来完成消息回调,触发GUI执行对应的操作. 这种方式简单易行,对萌新友好,且具备跨线程操作的功能. 但是postmessage 也有自身的缺陷:
为了解决GUI 跨线程操作界面的导致主线程崩溃的情况, C++ 11 终于推出了自己的thread 类
thread 类提供detach() 的方法, 让worker线程也具备了操作GUI的能力.
在GUI开发中, 通过使用function 和 thread等C++ 11 新特性,能够更便捷的开发出高质量的程序, 同时回避开发过程中的问题。