指向成员函数的向量

时间:2014-01-14 09:43:28

标签: c++ vector function-pointers

我正在尝试编写一个程序,该程序创建一个包含 vector 指向成员函数的指针的类,其中包含add()remove()成员函数。 我写的代码是 -

1    #include <iostream>
2    #include <vector>
3   using namespace std;
4    
5    typedef void(*classFuncPtr)();
6    
7    class FunctionVectors
8    {
9    private:
10      vector<classFuncPtr> FunctionPointerVector;
11    public:
12      FunctionVectors(){}
13      void add(classFuncPtr funcPtr);
14      void remove(int index);
15      void run();
16      void a(){cout<<"a: Why are you calling me?"<<endl;}
17    };
18    
19    void FunctionVectors::add(classFuncPtr funcPtr)
20    {
21      FunctionPointerVector.push_back(funcPtr);
22    }
23    
24    void FunctionVectors::remove(int index)
25    {
26      FunctionPointerVector.erase(FunctionPointerVector.begin() + index);
27    }
28    
29    int main()
30    {
31      FunctionVectors f;
32      classFuncPtr fv = &(classFuncPtr)FunctionVectors::a;
33     
34      f.add(fv);
35      f.run();
36     
37      return 0;
38  }

但是,它在第​​32行显示错误 -

error C2440: 'type cast' : cannot convert from 'void (__thiscall FunctionVectors::* )(void)' to 'classFuncPtr'  

请告诉我如何修改它才能正常工作。

提前致谢。

2 个答案:

答案 0 :(得分:5)

typedef void(*classFuncPtr)();

这不是指向方法的指针,而是指向函数的指针。方法与函数不同,因为它在上下文中被调用:需要this才能正常工作。

请记住,在C ++中,您只能创建指向特定类方法的指针向量。因此,您将无法在该向量中保留指向不同类的两种方法的指针。

解决方案 - 正如评论中所建议的那样 - 是使用std::functionboost::function以及可能是C ++ 11 lambdas,因为它们比简单的指向成员的指针提供了更多的灵活性。

如果要实现事件机制,请考虑使用仿函数而不是方法:

  1. 为事件处理程序创建基类:

    class MyEventHandler
    {
    public:
        virtual void operator()(void * sender, int data) = 0;
    }
    
  2. 创建这些的简单向量:

    std::vector<MyEventHandler *> MyEvent;
    
  3. 在班级中创建特定处理程序:

    class MyClass
    {
    private:
        class SpecificEventHandler : MyEventHandler
        {
        public:
            void operator()(void * sender, int data)
            {
                std::cout << "Event handled!";
            }
        }
    
    public:
        SpecificEventHandler Handler;
    
        MyClass()
        {
        }
    }
    
  4. 将处理程序挂钩到您的活动:

    MyEvent.push_back(&(myClassInstance.Handler));
    
  5. 从内存中编写的代码,可能无法编译,但你应该明白这一点。

答案 1 :(得分:1)

std::function< void() > 

看起来像您正在寻找的签名。如果它在您的C ++版本中不可用,但您可以使用boost,那么您可以在boost中找到它。查找适用于std的适当标题的文档。

要为成员函数创建一个,您需要绑定它,并将其绑定到FunctionVectors::a(),您需要一个FunctionVectors的实例来调用它。

在您的示例中,我将为您创建typedef

typedef std :: function&lt; void()&gt; classFuncPtr; //实际上是一个命名错误的typedef

int main()    {        FunctionVectors f;        classFuncPtr fv = std :: bind(&amp; FunctionVectors :: a,f);    }

或者如果你真的有lambda的C ++ 11你可以做

   classFuncPtr = [ f ]() { f.a() );

在你的情况下,我认为你并不真正想要一个免费的功能,你总是想要一个你想要的班级的成员功能。

   typedef void (*FunctionVectors::classFuncPtr )();

你会用

    (this->*func)(); 

调用它