向左右向右走 —— 小时了了的技术博客

关注C++开发技术、架构设计、软件项目管理、软件产品管理等

posts - 24,comments - 59,views - 36386

  我们假设这样一种应用场景,有两个类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();

 

 

  我们观察上面的代码,看看有什么问题:

  1. 两个类中B对A产生了一个依赖关系,这让人有点不爽;
  2. 哪天我们想用另外一个类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();
    }
};
 
调用方法和之前差不多,只是把赋值操作的对象由A的指针改成了A的成员函数:
1
2
3
4
A a;
B b;
b.AFunc = std::bind(&A::Func, &a);
b.UseA();
  
  代码看起来复杂了那么一点点,但是从代码逻辑的角度看改进了很多:
  1. B和A彻底解耦,只在运行期才B的某个对象对A的某个对象产生依赖,而且这种依赖完全在调用者的控制之下;
  2. 我们想把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库作为替代方案,用法完全相同。
posted on   小时了了  阅读(544)  评论(3编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
< 2010年12月 >
28 29 30 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示