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

时间:2012-02-24 07:46:31

标签: c++

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

6 个答案:

答案 0 :(得分: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 );
}

更简洁的是以这种方式构建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;
};

这里的优点是可以很容易地调试。

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

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

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

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

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

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

答案 1 :(得分:2)

回调功能: Callback functions in c++

http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.../c10557

虚拟功能: http://en.wikipedia.org/wiki/Virtual_function

这些是你通过谷歌搜索得到的结果!没有什么可以补充的。我不认为回调和虚函数之间存在任何差异

答案 2 :(得分:2)

回调函数是从程序的其他部分引用的函数。想一想如何将指针传递给周围的对象 - 可以使用函数完成相同的操作。然而,对于初级程序员来说,这可能被认为是一个具有挑战性的话题。

虚函数是指可以由子类实现的函数。阅读术语polymorphism

答案 3 :(得分:2)

回调函数实现控制反转(一种重要的设计模式)。虚函数实现多态(编程范式)。从根本上说,它们是无关的,因为它们从两个不同的角度来看待代码。实现控制反转的一种方法是通过抽象基类,其虚函数成为有效的回调函数。大多数时候,当人们听到术语回调函数时,它是关于在C中定义的API,它不能使用抽象基类和虚函数。在这种情况下,需要一个自由函数(通常为extern "C");在大多数情况下,此函数将接收void*参数以允许将数据传递给它。

答案 4 :(得分:1)

回调函数是您作为参数传递的函数,可以在其他地方执行。

虚函数是C ++中多态的构建块之一。这意味着在基类的对象上调用此方法将从继承链中最上层的派生类调用相同的方法。

答案 5 :(得分:1)

回调函数很难追踪,但有时它非常有用。特别是在设计图书馆时。回调函数就像要求你的用户给你一个函数名,你会在一定条件下调用该函数。

void cbfunc()
{
    printf("called");
}

int main ()
{
     /* function pointer */
    void (*callback)(void);

    /* point to your callback function */
    callback=(void *)cbfunc;

   /* perform callback */
   callback();

   return 0;
}

虚函数意味着它通过覆盖函数来实现多态性。