C++的另一种抽象流派:bind+function

  C++一直提供了基于多态的抽象设计方式,让我们摆脱了C语言中type+callback+void*抽象方式,从而可以将数据与方法封装在一起,更清晰的描述代码。

 

  C++的抽象基于多态实现,一个简单的例子:

#include <iostream>
class A
{
public:
    virtual ~A()
    {
        /* std::cout << __FUNCTION__ << std::endl; */
    }
    virtual void Func(void) = 0;
};

class B: public A
{
public:
    virtual ~B()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
    virtual void Func(void)
    {
        std::cout << "B::Func" << std::endl;
    }
};

class C: public A
{
public:
    virtual ~C()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
    virtual void Func(void)
    {
        std::cout << "C::Func" << std::endl;
    }
};

void IDoNotKnowAnyDetail(A *base)
{
    base->Func();
    delete base;
}

int main(int argc, char *const argv[])
{
    A *pb = new B();
    A *pc = new C();
    IDoNotKnowAnyDetail(pb);
    IDoNotKnowAnyDetail(pc);
    return 0;
}

 

输出:

B::Func
~B
C::Func
~C

  A是抽象基类, B和C分别实现Func, 然后有一个IDoNotKnowAnyDetail函数依赖了A抽象, 对细节不知情.

 

  这是目前C++, 无论是经典教材还是大学教材里都讲的基础知识, 那么bind+function如何达到类似的抽象能力呢, 看下面的代码:

#include <iostream>
#include <algorithm>
#include <tr1/memory>
#include <tr1/functional>

class B
{
public:
    ~B()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
    void FuncB(void)
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};

class C
{
public:
    ~C()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
    void FuncC(void)
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};

void IDoNotKnowAnyDetail(std::tr1::function<void ()> func)
{
    func();
}

int main(int argc, char *const argv[])
{
    std::tr1::function<void ()> func_b = std::tr1::bind(&B::FuncB, std::tr1::shared_ptr<B>(new B()));
    std::tr1::function<void ()> func_c = std::tr1::bind(&C::FuncC, std::tr1::shared_ptr<C>(new C()));
    IDoNotKnowAnyDetail(func_b);
    IDoNotKnowAnyDetail(func_c);
    return 0;
}

 

输出:

FuncB
FuncC
~C
~B

  代码尽量和上面实现相似, 以便比较. 可以看到IDoNotKnowAnyDetail函数的参数是function<void ()>, 但它依旧表现出了与多态实现一样的输出, 与多态版本相比还少实现了一个类A, 很有意思.

  bind+function版本我使用了shared_ptr取代了raw指针, 在多线程环境下线程间传递func_b, func_c是可以无需考虑内存释放的, 对象会随着function的析构而一起释放, 这一点也比较实用.

  

  两种风格在完成工作的能力方面暂时没感觉到什么差别, 但bind+function是一种回归C风格的方案, 但同时保留了数据与方法的封装性, 并不是一种倒退.

  性能方面, 多态风格由于虚函数的原因, 性能稍有损耗但根本不足为患, bind+function风格性能妥妥的, 同时避免了多态引入的继承体系, 一定程度降低代码复杂度.

  可读性方面, 我认为多态实现更易读, 因为它基于面向对象的语义, 还是符合人类习惯的, bind+function风格导致多个实现类彼此没有明显关联, 也许会稍微阻碍一下理解.

  实现方面, bind+function的实现是比较高端, 照我的意思说是挺暗黑的(C++这方面的难度与复杂度我真无心深究了), 但并不耽误使用, 毕竟C++11已经纳入标准, 即便我们不愿意去理解底层实现, 但一个定义和行为明确的黑盒利器依旧是我们值得选择的. 多态实现就不多说了, 大家都有经验.

  

  代码风格方面, 我认为还是统一而不要混用, 否则对项目维护可能是个小灾难.

  

posted @ 2013-08-05 23:17  cppisnotbad  阅读(762)  评论(0编辑  收藏  举报