C++中的成员函数指针

4

这其实是为了一个国际象棋程序,但是代码太长不能在此贴出,所以我将使用一个更简单、不相关的例子:

假设我有一个这样的对象:

class A{
    int x1;
    int x2;
public:
    int Average(){ return (x1+x2)/2; }
};

我希望有一个向量称为AveragesList,它存储所有对象的x1和x2值的平均值(或指向它们的指针)。因此我尝试这样做:
vector<int>* AveragesList;

class A{
    int x1;
    int x2;
public:
    int Average(){ return (x1+x2)/2; }
    A(){ AveragesList.push_back(this->Average); } //trying to add pointer to member function Average() to AveragesList
};

但是当我尝试这样做时,会收到一个消息,说“只有指向绑定函数的指针才能用于调用函数”。有什么解决方法吗?我不想简单地将x1和x2的平均值放在AveragesList中,因为如果x1或x2发生变化,AveragesList中的值也会发生变化。另外,我的书上说不要在C++类中使用公共变量,所以我不确定是否应该使用一个。


3
为什么你想要在 vector 中存储成员函数指针而不是平均值本身?成员函数指针只是类中成员的偏移量,对于对象的类来说这个偏移量都是一样的。另外,你不能在没有对象的情况下使用它,因为你没有存储任何对象以使用成员函数指针。你所需要的只是 AveragesList.push_back(this->Average());,其中:vector<int> AveragesList; - Alok Save
因为如果x1或x2发生变化,AveragesList中的值不会更新。 - john smith
即使您存储了成员指针,它也不会自动更新平均值。这不像回调函数,可以在不被要求的情况下执行某些操作。每次更新平均值时,您都需要手动更新包含平均值的向量。 - Alok Save
这听起来非常类似于观察者模式 - Jerry Coffin
3个回答

4
在C++11之前,没有内置的处理闭包的方法,因此在不使用boost等库的情况下解决问题的最简单方法是:除了您的x1和x2变量外,定义一个名为average的整数成员变量。创建对象时将平均值设置为正确的值,并在每次更改x1或x2时更新它。将指针存储在列表中,并使用它来访问平均值。
这不如实时计算结果好。如果您正在使用C++11,则有更好的解决方案:
#include <iostream>
#include <vector>
#include <functional>

class A{
    int x1;
    int x2;
public:
    A(int _x1, int _x2) : x1(_x1), x2(_x2) {}
    int Average(){ return (x1+x2)/2; }
    void setX1(int _x1) { x1 = _x1; }
    void setX2(int _x2) { x2 = _x2; }
};

using namespace std;

int main() {
    vector<std::function<int()>> v;
    A a1(1, 5);
    A a2(2, 8);
    v.push_back([&]{return a1.Average();});
    v.push_back([&]{return a2.Average();});
    for (int i = 0 ; i != v.size() ; i++) {
        cout << v[i]() << endl;
    }
    a1.setX1(7);
    a2.setX2(32);
    for (int i = 0 ; i != v.size() ; i++) {
        cout << v[i]() << endl;
    }
    return 0;
}

这个“C++11”是什么意思?为什么C++不能优雅地就此消亡呢? - paulsm4

1

如果您不想存储“average”的当前值...为什么不存储对“A”的引用呢?

示例:

Class A{
    int x1;
    int x2;
public:
    A (int x1, int x2) { this->x1 = x1; this->x2 = x2; }
    int Average(){ return (x1+x2)/2 }
};

...

int
main (int argc, char *argv[])
{
  vector<A> averagesList;
  averagesList.push_back (new A(3, 4));
  ...

1
这段代码甚至无法编译。你的向量存储了一个类型为 A 的对象,而你正在尝试将指向 A 的指针 A* 推入该向量中。 - Alok Save
我认为你的代码是用C#编写的,而原始代码是用C++编写的。 - templatetypedef
这并不是要编译的。我试图表达的观点是:1)函数指针向量不是正确的方法;2)对象引用向量可能是一个可行的替代方案。 - paulsm4

1
要做你想做的事情(我猜测),你还需要存储对象的指针,以便调用函数时使用。
#include <vector>
#include <iostream>

class A {
  int x1,x2;
public:
  int Average(){ return (x1+x2)/2; }
  A(int a, int b);
};

std::vector< A* > objectVec;
std::vector< int (A::*)() > functionPtrVec;

A::A(int a, int b):
  x1(a), x2(b) {
  objectVec.push_back(this);
  functionPtrVec.push_back(& A::Average);
}

int main() {
  A a1(1,3);
  A a2(10,20);

  for (int k=0; k<objectVec.size(); k++) {
    int (A::* memberFuncPtr)() = functionPtrVec[k];
    A*object = objectVec[k];
    std::cout << (object->*memberFuncPtr)() << std::endl;
  }
  return 0;
}

你可以使用一个 pair 将它们存储在同一个 vector 中,或者定义自己的成员函数类,该类存储对象、成员函数指针,并具有一个 () 运算符。
希望对你有所帮助。

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