Массив функций класса

Чтобы сохранить функции класса в массиве, следующая ссылка http://sourcemaking.com/design_patterns/state/cpp/1 содержит код, как показано ниже (Machine - это имя класса).

void(Machine:: *ptrs[])() = 
 {
 Machine::off, Machine::on
 };

Пример в этой ссылке не компилируется с ошибкой компилятора g++, как показано ниже

$ g++ state.cpp 
state.cpp: In function ‘int main():
state.cpp:89:18: error: invalid use of non-static member function ‘void Machine::off()
state.cpp:89:32: error: invalid use of non-static member function ‘void Machine::on()
state.cpp:97:15: error: expected unqualified-id before ‘* token

Я использую g++ версию 4.5.2

$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Может ли массив быть определен таким образом, я не могу найти такое ограждение массива, как это где-то еще. Если пример правильный, почему он не компилируется.

3 ответа

Если вы определите typedef для своих функций-членов, вы значительно упростите свой код.

class Machine
{
public:
 void on(){}
 void off(){}
};


int main()
{

 typedef void (Machine::*MachineFunctionPtr)();

 MachineFunctionPtr temp[] = { &Machine::off , &Machine::on };


 //To invoke a function use this syntax
 Machine mymachine;
 ((mymachine).*(temp[1]))();

Бытие говорит, что ваша ошибка связана с отсутствием "&" перед именем функции.

Если вы не хотите использовать typedef, правильный способ - это что-то вроде

void(Machine:: *ptrs[])() = 
{
 &Machine::off, &Machine::on
};
Machine fsm;
int num;
while (1)
{
 cout << "Enter 0/1: ";
 cin >> num;
 ((fsm).*(ptrs[num]))();
}


Чтобы иметь возможность добавлять указатели-члены-члены в свой массив, вам нужно будет добавить свои идентификаторы с адресом-оператором &.

Пример:

struct Obj {
 void func_1 () {}
 void func_2 () {}
};

int
main (int argc, char *argv[])
{
 void (Obj::* pointers[]) () = {
 &Obj::func_1, &Obj::func_2
 };
}


Это тем больше c++ способ сделать это:

#include <vector>
#include <iostream>

struct A {
 typedef void (A::*memfpt)();

 A() : arr( { &A::foo, &A::bar } )
 {}

 void foo()
 {
 std::cout<<"foo"<<std::endl; }="" void="" bar()="" {="" std::cout<<"bar"<<std::endl;="" std::vector<="" memfpt=""> arr;
};

int main() {
 A a;

 for ( auto &it : a.arr )
 {
 (a.*it)();
 }
}
</std::endl;></iostream></vector>

Вместо необработанного массива я использовал std :: vector, и вместо этой невыразимой мерзости я использовал typedef.

Ваш конкретный пример не компилируется, потому что:

  1. строка 97: (fsm. *ptrs[num])(); должен быть (fsm.*ptrs[num])(); - вам нужно удалить это пространство, потому что вызов указателя на функцию-член должен выполняться с помощью .* или ->*
  2. line 89: Machine::off, Machine::on должен быть &Machine::off, &Machine::on потому что именно так вы получаете указатель на функцию-член.

licensed under cc by-sa 3.0 with attribution.