我们假设这样一种应用场景,有两个类A和B,在B中需要调用A的一个方法(成员函数)。那么我们的代码可能是这个样子的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class A { public : void Func( void ) { printf ( "%s\r\n" , __FUNCTION__); } }; class B { public : void UseA() { a->Func(); } public : A* a; }; |
调用代码是这样的:
1 2 3 4 | A a; B b; b.a = &a; b.UseA(); |
我们观察上面的代码,看看有什么问题:
- 两个类中B对A产生了一个依赖关系,这让人有点不爽;
- 哪天我们想用另外一个类C替代A的作用意味着我们要重写B,这让人更不爽;
上面两个问题实质上是耦合的问题,依赖关系是强耦合,耦合度高了代码可读性和可维护性都会变差。
我们分析一下这两个类的关系,在B中调用了A的一个成员函数所以产生了依赖。而这个调用完全可以使用函数指针,由于C++的函数指针使用起来太过麻烦,所以我们用function代替。改进后的B的定义如下:
1 2 3 4 5 6 7 8 9 10 | class B { public : std::function< void ( void )> AFunc; void UseA( void ) { if (AFunc != NULL) AFunc(); } }; |
1 2 3 4 | A a; B b; b.AFunc = std::bind(&A::Func, &a); b.UseA(); |
代码看起来复杂了那么一点点,但是从代码逻辑的角度看改进了很多:
- B和A彻底解耦,只在运行期才B的某个对象对A的某个对象产生依赖,而且这种依赖完全在调用者的控制之下;
- 我们想把A替换成C,那么就换把,改一下调用代码就可以搞定,B的定义代码一行不动——这正是我们追求的灵活性和扩展性;
1 2 3 | C c; b.AFunc = std::bind(&C::Func, &c); b.UseA(); |
作为C++ 0x的新特性,std::function和std::bind目前只在VS2010中才被支持,用其他编译器的同学可以用boost库作为替代方案,用法完全相同。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步