使用回调函数和抽象基类的虚函数有什么区别?

mac*_*.ma -2 c++

像标题一样.作为一名新的程序员,了解我的项目机制以及使用它们的不同之处非常重要.任何人都可以给我一个答案,谢谢!

Cas*_*Cow 7

虚函数是提供回调的一种机制,但它不是唯一的机制.

回调的一般性是您作为参数,方法或调用方法的对象传入,该方法将由您传递给它的函数调用,或者将由该函数存储,以便稍后调用事件发生了.

实现这种机制的一种方法是将指针或引用传递给从基类派生的对象并实现虚函数.

另一种方法是传入一个函数指针.

还有一种方法是传入一个带有函数指针的对象,这就是boost函数的作用 - 用于提升函数的构造函数(通常boost::bind)巧妙地为你构造这样一个对象.

在C++ 11中,您将能够动态构造一个未命名的函数作为回调传递.这通常被称为lambda.

更多关于使用虚函数作为回调的机制.它看起来像一个很好的事情:

class Handler
{
  public:
   virtual ~Handler() {}
   virtual void process( std::string const& message ) = 0;
};

void getMessage( Handler& handler )
{
    std::string str = getAMessage();
    handler.process( str );
}
Run Code Online (Sandbox Code Playgroud)

更简单的是以这种方式构造Handler:

class Handler
{
  public:
    virtual ~Handler() {}
    void process( std::string const& message ) 
    {
       // can log or put in a breakpoint here on debugging
        doProcess( message );
    }

   protected: // or private
       virtual void doProcess( std::string const& message ) = 0;
};
Run Code Online (Sandbox Code Playgroud)

这里的优点是它易于调试.

如果需要管理Handler对象的生命周期,即回调异步发生,则会变得更加复杂.然后你必须使用a,shared_ptr<Handler>以便双方都持有一个引用,并且它将被管理.

通过常规回调函数,您可以找到一个巨大的优势,即对象可以保存额外的信息.回调本身只能接受固定数量的参数,并且在回调中,通常会使用void*并且必须将其转换为某些内容以获取额外信息.使用该类允许您将该信息保存在成员变量中,并允许该类在调用其方法后保留状态.

使用它的开销是你必须创建这样的抽象类,然后从中派生类,你可能会发现自己这样做了很多.

这是boost函数和bind变得非常有用的地方.你真正想要的是一个具有特定签名的函数,而不必创建额外的类来处理这个回调.因此,您可以更快地编程这种情况.

然而,不幸的是,它确实也有缺点.升级函数要难以调试.虽然您不必小心管理boost函数本身的生命周期,但您必须注意传递给它的参数.它只会盲目地存储它们传递它们的方式.如果您boost::ref将对局部变量的引用作为reference-holder()传入,它确实会存储此引用,如果在调用该函数之前它超出范围,您可能很难找到此错误.

尽管如此,我建议使用库特性(注意还有std :: function和std :: bind,尽管当lambdas成为编译器的标准时,对它们的要求会少得多).