成员指针函数列表

时间:2010-09-15 18:07:32

标签: c++ stl pointer-to-member

说我有课:

class A
{
public:
  void doSomething();
}

doSomething在哪里做了明确依赖于A实例的内部状态的东西。

现在,我有一种情况,我有很多类型A的东西,但我只想从它们的一个严格的子集中调用doSomething,所以我想把它们粘在列表上。特别是,我真正想做的是将指针粘贴到列表中的单个doSomethings()。

我可以这样做吗?我是否声明它:

std::list<(A::*)()> aDoSomethings;

我读了this entry,这是有道理的,如果需要,我会走那条路。

6 个答案:

答案 0 :(得分:3)

您是否考虑过简单的面向对象方法:

struct Can_Do_Something
{
    virtual void doSomething() = 0;
};

class A : public Can_Do_Something
{
    ...
};

std::list<Can_Do_Something*> my_list;

my_list[n]->doSomething();

这限制性地保持对您计划通过列表访问的A接口部分(通过Can_Do_Something类型继承)的访问。它记录并执行该限制。

如果您偏好更接近原始愿景的事物,请考虑......

#include <iostream>
#include <vector>
#include <boost/function.hpp>

struct A
{
    A(int n) : n_(n) { }

    int f(int x) { std::cout << "A::f() this " << (void*)this
                           << ", n_ " << n_
                           << ", x_ " << x << '\n'; }

    int n_;
};

int main()
{
    typedef boost::function<int (int n)> Function;
    typedef std::vector<Function> Functions;

    Functions functions;
    A a1(1), a2(2), a3(3);

    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a1));
    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a2));
    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a3));

    for (Functions::iterator i = functions.begin();
            i != functions.end();
            ++i)
        (*i)(42);
}

这里,boost :: function用于创建对您感兴趣的特定函数的回调。

答案 1 :(得分:2)

您似乎对成员函数指针的工作原理感到困惑。对于给定的类,任何给定函数只有一个实例。它们通过使用隐式参数this来区分。基本上,您可以假装您有以下映射。

struct Struct { void Function(); }
Struct a;
a.Function();

变成

struct Struct { }
void Function(Struct* this);
Struct a;
Function(&a);

因此,如果您有一堆Struct个对象,并且想要在其中一小部分上调用Function,则不存储Function,而是存储{{1} }}

当您有多个功能时,会使用指向成员函数的指针,您需要选择性地调用它们。因此,如果您的类中有两个函数,它们都没有参数并返回void,Struct可以指向它们中的任何一个。但它仍然指向一个特定的功能,其中只有一个。您仍需要提供void (Struct::*)()参数。

this

不是最好的例子,但它得到了重点。您可以使用成员函数混合和匹配对象。

*编辑:没有容器阻碍的示例

struct Struct {
  Struct(int v) : value(v) { }
  void One() { cout << "one: " << value << endl; }
  void Two() { cout << "two: " << value << endl; }
  int value;
};

int main()
{
  std::vector<Struct> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  std::vector<void (Struct::*)()> f;
  f.push_back(&Struct::One);
  f.push_back(&Struct::Two);
  f.push_back(&Struct::One);

  for(int i = 0; i < 3; ++i)
    (v[i].*f[i])();
}  

请注意额外的括号。 Struct a(5), b(10); void (Struct::*one)() = &Struct::One; void (Struct::*two)() = &Struct::Two; (a.*one)(); (b.*one)(); (a.*two)(); (b.*two)(); 不足。

答案 2 :(得分:1)

成员函数指针没有指向特定实例的指针:它描述了如何使用this指针和参数调用具有特定签名的成员函数。

相反,将指向您关注的对象的指针放入列表中,然后遍历该列表,在每个项目上调用doSomething

答案 3 :(得分:1)

你应该检查一下boost :: function和boost :: bind。

答案 4 :(得分:0)

是的,你可能想要这样的东西:

#include <vector>
#include <iostream>
#include <string>

using namespace std;

class A {
  string m_name;

  public:
    A(const string& name) : m_name(name) {} 
    void doSomething() { cout << m_name << "::doSomething()" << endl; }
};

int main(void) {
  A f1("f1");
  A f2("f2");
  A f3("f3");
  A f4("f4");
  vector<A*> foo_list;
  foo_list.push_back(&f1);
  foo_list.push_back(&f3);

  for (vector<A*>::iterator it = foo_list.begin(); it != foo_list.end(); *it++) {
    static_cast<A*>(*it)->doSomething();
  }

  return 0;
}

答案 5 :(得分:0)

如果我的理解是正确的,你想要一个指向函数成员的指针列表必须是doSomething()吗?

然后你可以有一个指向你的类成员的函数指针列表,但你需要提供相关的对象,那么为什么不简单地保留一个(指向)对象的列表呢?