C++:不同函数的成员函数指针数组

8

我有一个类A,其中包含成员函数foo()和bar(),它们都返回指向类B的指针。如何在类A中声明包含函数foo和bar的数组作为成员变量?如何通过该数组调用这些函数?

3个回答

21

成员函数指针的语法是 ReturnType (Class::*)(ParameterTypes...),例如:

typedef B* (A::*MemFuncPtr)(); // readability
MemFuncPtr mfs[] = { &A::foo, &A::bar }; // declaring and initializing the array
B* bptr1 = (pointerToA->*mfs[0])(); // call A::foo() through pointer to A
B* bptr2 = (instanceOfA.*mfs[0])(); // call A::foo() through instance of A

查看例如这篇InformIT文章,了解有关成员指针的更多详细信息。

您可能还想了解Boost.BindBoost.Function(或其TR1等效物),它们允许您将成员函数指针不透明地绑定到实例:

typedef boost::function<B* ()> BoundMemFunc;
A instanceOfA;
BoundMemFunc mfs[] = { 
    boost::bind(&A::foo, &instanceOfA), 
    boost::bind(&A::bar, &instanceOfA) 
};
B* bptr = mfs[0](); // call A::foo() on instanceOfA

如果要将这样的数组用作成员变量,请注意您无法使用成员初始化器列表来初始化数组。因此,您只能在构造函数体中对其进行赋值:

A::A {
    mfs[0] = &A::foo;
}

如果可能的话,使用可以在该位置进行初始化的类型,例如std::vectorboost::array,否则请重新考虑代码逻辑。

struct A {
    const std::vector<MemFuncPtr> mfs;
    // ...
};

namespace {
    std::vector<MemFuncPtr> init_mfs() {
        std::vector<MemFuncPtr> mfs;
        mfs.push_back(&A::foo);
        mfs.push_back(&A::bar);
        return mfs;
    }
}

A::A() : mfs(init_mfs()) {}

1
@DeadMG: 我提到了 TR1 版本,但选择了 Boost 版本,因为它有最广泛的可用性。我个人认为 C++0x 版本并不普及,而且新标准也尚未最终确定。 - Georg Fritzsche
啊,原来是这样。因为我自己有一个C++0x编译器,所以我不习惯看到boost变量。 - Puppy

2
你需要寻找的是成员函数指针。以下是一段简短的示例代码,展示了它们的声明和用法:
#include <iostream>

class B {
public:
  B(int foo): foo_(foo) {
    std::cout << "Making a B with foo_ = " << foo_ << std::endl;
  }
  ~B(void) {
    std::cout << "Deleting a B with foo_ = " << foo_ << std::endl;
  }
  int foo_;
};

class A {
public:
  A(void) {
    funcs_[0] = &A::foo;
    funcs_[1] = &A::bar;
  }

  B* foo(void) {
    return new B(3);
  }

  B* bar(void) {
    return new B(5);
  }

  // Typedef for the member function pointer, for everyone's sanity.
  typedef B* (A::*BMemFun)(void);
  BMemFun funcs_[2];
};

int main(int argc, char *argv[]) {
  A a;
  for (int i = 0; i < 2; ++i) {
    A::BMemFun func = a.funcs_[i];
    // Call through the member function pointer (the .* operator).
    B* b = (a.*func)();
    delete b;
  }
  return 0;
}

我在C++ FAQ中关于成员函数指针的部分找到了这些信息。


-1
C++不古老(即C++11及以后版本)使所有这些变得更容易。在现代C++中,您可以这样做
#include <vector>
class B;
class A {
   public:
    B* foo() {
        // return something;
        return nullptr;
    }

    B* bar() {
        // return something;
        return nullptr;
    }
    
    //C++ 11: functional brings std::function, which has zero overhead 
    //but is actually a useful type with which one can work
    std::vector<std::function<B*()>> container;

    /* [=]() { return foo(); }
     * that's a lambda. In practice it "compiles away", i.e. calling
     * the lambda function is the same as calling foo or bar directly
     * Note how [=] means we're passing in "this", so that we can 
     * actually call foo().
     */
    A() : container{{[=]() { return foo(); }}, {[=]() { return bar(); }}} {}
};

(在godbolt编译器上尝试)

这里有一个更完整的示例,展示了如何使用它们。


一个架构上的注意事项:小心处理指向非静态成员函数的指针。如果你的 A 实例被销毁了,但你仍然持有一个成员函数的函数句柄会发生什么?没错,地狱会冻结:再也没有对象拥有这个方法,结果将是灾难性的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接