Как я могу это сделать? (Следующий код НЕ работает, но я надеюсь, что он объясняет идею.)

class MyClass  
{  
    ....  
 private:
    int ToBeCalled(int a, char* b);

    typedef (MyClass::*FuncSig)(int a, char* b);

    int Caller(FuncSig *func, char* some_string);
}

Я хочу позвонить вызывающему абоненту примерно так:

Caller(ToBeCalled, "stuff")

И пусть Caller вызовет ToBeCalled с любыми параметрами, которые, по его мнению, необходимо передать. Если это вообще возможно, я хочу, чтобы все было инкапсулировано в частной части моего класса. На самом деле у меня было бы около 50 функций, таких как ToBeCalled, поэтому я не вижу способа избежать этого.

Спасибо за любые предложения. :)

3
Stigma 10 Ноя 2009 в 07:17
Все 50 функций имеют тот же список параметров, что и "int ToBeCalled (int a, char * b);", или могут быть разными, например, "int Another (int a, char * b, short c);"?
 – 
Test
10 Ноя 2009 в 07:25

2 ответа

Лучший ответ

Вы почти там. Вам не хватает возвращаемого типа из typedef, он должен быть

typedef int (MyClass::*FuncSig)(int, char*);

Теперь вам просто нужно правильно его использовать:

int Caller(FuncSig func, int a, char* some_string)
{
    return (this->*func)(a, some_string);
}

Вы хотите передать простые экземпляры FuncSig, а не FuncSig* - FuncSig* - это указатель на указатель на функцию-член с дополнительным ненужным уровнем косвенности. Затем вы используете оператор со стрелкой-звездочкой (не официальное название), чтобы вызвать его:

(object_to_be_called_on ->* func)(args);

Для объектов, не являющихся указателями (например, объектов в стеке или ссылок на объекты), вы используете оператор точка-звезда:

MyClass x;
(x .* func)(args);

Кроме того, будьте осторожны с приоритетом операторов - операторы «стрелка-звезда» и «точка-звезда» имеют более низкий приоритет, чем вызовы функций, поэтому вам нужно поставить дополнительные круглые скобки, как я сделал выше.

7
Adam Rosenfield 10 Ноя 2009 в 07:23
О мой Бог. Не могу поверить, что был так близок. Я возился с этим кодом в течение 3 часов, и я действительно перепробовал все, что вы опубликовали в какой-то момент ... но, видимо, я пропустил одну точную комбинацию, которая была ответом. Большое спасибо за быстрый ответ - я сожалею, что не приехал сюда раньше! :)
 – 
Stigma
10 Ноя 2009 в 07:40

Я предполагаю, что вы уже пробовали Caller(MyClass::ToBeCalled, "stuff"), но есть ли какая-то особая причина, по которой вам нужен указатель на функцию? Также опубликуйте фактическую ошибку компилятора.

0
Stephen Newell 10 Ноя 2009 в 07:23
Спасибо за ваше предложение, и да, я пробовал это. :) Я реализую обработчик свойств для Windows 7, но библиотеки, о которых я говорю, (тоже) любят функции. Добавьте несколько устаревших версий файлов, лежащих поблизости, и вам придется проверять каждый более старый формат файла, если новый не реализован. Функция Caller в этом случае - это тестирование различных форматов версий, а ToBeCalled - фактические функции чтения, которые интерпретируют дефолтность и тому подобное. По крайней мере, все форматы имеют один и тот же интерфейс. :)
 – 
Stigma
10 Ноя 2009 в 07:58