关于成员函数指针的使用(和有用性)vs直接调用成员函数

时间:2010-07-14 13:06:36

标签: c++ pointer-to-member

我是指向成员函数的新手,我想知道它们的优点和缺点。

具体来说,请考虑一下:

#include <iostream>
#include <list>

using namespace std;

class VariableContainer;

class Variable
{
public:
  Variable (int v) : value (v), cb_pointer (0) {}
  ~Variable () {}

  void SetCallback (void (VariableContainer::*cb)(int)) {
    cb_pointer = cb;
  }
  void FireCallback (void) {
    /* I need a reference to a VariableContainer object! */
  }

private:
  int value;
  void (VariableContainer::*cb_pointer) (int);
};

class VariableContainer
{
public:
  VariableContainer () {}
  ~VariableContainer () {}

  void AddVar (Variable &v) {
    v.SetCallback (&VariableContainer::Callback);
  }
  void Callback (int v) { cout << v << endl; }
};

int main ()
{
  Variable v (1);
  VariableContainer vc;

  vc.AddVar (v);
  v.FireCallback();

  return 0;
}

如评论中所述,要触发回调(FireCallback),我需要对现有VariableContainer对象进行一些引用,该对象应作为VariableContainer::AddVar (...)的附加参数提供。 现在:

  1. 我应该使用指向成员函数的指针吗?或者我应该直接调用Callback (...)(因为我有一个指向VariableContainer对象的指针)?
  2. 每种解决方案的优点和缺点是什么?
  3. TIA, JIR

2 个答案:

答案 0 :(得分:2)

根据将来会发生什么变化,您可以决定:

  • 其他函数将由变量的FireCallback =&gt;调用指向mf的指针可能很有用,但其他机制更多是c ++ ish
  • 只会调用'回调'功能=&gt;坚持直接打电话给arg->CallBack()

问题的一个可能解决方案是使用接口层:这只不过是Observer模式的实现。这是一个更多的OO,因此冗长,但语法更容易。

class Observer {
public:
    virtual ~Observer(){};
    virtual void callback( int v ) = 0;
};

// actual implementation
class MyCallbackObserver : public Observer {
    virtual void callback( int v ) { std::cout << v << std::endl; }
    void some_other_method( int v ) { std::cout << "other " << v ; }
};

你的Variable课将有一个装满观察员的容器:

class Variable {
public:
   std::vector<Observer*> observers; // warning: encapsulation omitted
   void FireCallback(){
      // assuming C++ 0x
      for( auto it : observers ) {
        (*it)->Callback( value );
      }
   }

如果需要在同一个对象上调用其他函数,可以引入一个包装器:

class OtherCaller: public Observer {
 public:
     MyObserver* obs;
     virtual void callback( int v ) { obs->some_other_method( v ); }
}

并将其添加到集合中:

Variable var;
MyObserver m;
OtherCaller mo;
mo.obs = &m;

var.observers.push_back(&m);
var.observers.push_back(&mo);

var.FireCallback();

答案 1 :(得分:1)

这取决于您的需求。

如果你只有一个回调函数,并且你总是知道它的名字,你也可以直接调用它。它更简单,更容易理解,并且不会涉及额外的变量。

如果您需要能够根据配置调用多个回调中的一个回调,那么成员函数指针会很有用:您可以将回调成员函数指针设置为您想要调用的实际回调,然后用于选择回调执行。