2014-01-14 4 views
0

Я пытаюсь написать программу, которая создает класс, который содержит вектор указателей на функции-члены, с 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

Я предлагаю вам использовать зЬй :: функцию вместо сырых указателей на функции (повышение :: функции, если вы не можете использовать C++ 11) –

+0

Посмотрите на 'std :: mem_fn'. –

+3

Если вы хотите сохранить указатель на функцию-член, вам понадобится [указатель на функцию-член] (http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions), а не простой указатель функции. Но более общий тип типа ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function), вероятно, будет легче справиться. –

ответ

3
typedef void(*classFuncPtr)(); 

Это не указатель на метод, а указатель на функцию. Метод отличается от функции, потому что он вызывается в контексте: для корректной работы требуется .

Имейте в виду, что на C++ вы можете создавать вектор указателей только для метода определенного класса. Таким образом, вы не сможете указывать указатели на два метода разных классов в этом векторе.

Решение, как предлагается в комментариях, - использовать std::function или boost::function и, возможно, C++ 11 lambdas, поскольку они обеспечивают гораздо большую гибкость, чем простые указатели.

Если вы хотите реализовать механизм событий, рассмотреть также с помощью функторов вместо методов:

  1. Создать базовый класс для обработчика событий:

    class MyEventHandler 
    { 
    public: 
        virtual void operator()(void * sender, int data) = 0; 
    } 
    
  2. Создание простой вектор из них:

    std::vector<MyEventHandler *> MyEvent; 
    
  3. Создание специальных обработчиков в y наши классы:

    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)); 
    

код, написанный по памяти, не может скомпилировать, но вы должны получить идею.

1
std::function< void() > 

похоже на подпись, которую вы ищите. Если он недоступен в вашей версии C++, но вы можете использовать boost, тогда вы заполняете его в boost. Посмотрите документацию для соответствующего заголовка, для std, для функции.

Чтобы создать его для функции-члена, вам необходимо связать его, а для привязки к FunctionVectors::a() вам понадобится экземпляр FunctionVectors, чтобы позвонить ему.

В вашем примере, я сделаю ЬурейеЕ для вас

ЬурейеГо станд :: функцией < недействительных()> classFuncPtr; // на самом деле плохо названный typedef

int main() { Функциональные векторы f; classFuncPtr fv = std :: bind (& FunctionVectors :: a, f); }

в качестве альтернативы, если у вас действительно есть C++ 11 с лямбды вы можете сделать

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

В вашем случае я думаю, вы действительно не хотите, свободную функцию, вы всегда хотите функцию члена вашей класс, который вы хотите.

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

и вы будете использовать

(this->*func)(); 

вызвать его

+0

Ни gcc, ни clang не нравится 'this (-> * func)();'. Они довольны еще круглыми скобками: '(this (-> * func))();'. –

+0

да я переместил открывающую скобку – CashCow

Смежные вопросы