2015-11-12 7 views
2

Я пытаюсь построить класс, который имеет функцию-член с методом в качестве аргумента. Методы определены в унаследованных классах. Я строй минимального примера:Передача унаследованного метода другому методу

#include <iostream> 

struct base 
{ 
    base() {} 

    int number(int (*f)(int)) 
    { 
     return f(1); 
    } 
}; 

struct option1 : base 
{ 
    int timesTwo(int i){return 2*i;} 
    option1() 
    { 
     std::cout << number(timesTwo); 
    } 
}; 

struct option2 : base 
{ 
    int timesThree(int i){return 3*i;} 
    int timesFour (int i){return 4*i;} 
    option2() 
    { 
     std::cout << number(timesThree); 
    } 
}; 

int main() 
{ 
    option1 a; //I would expect this to print "2" 
} 

Текущий синтаксис функции number для общей функции, но я не могу заставить его работать для метода любых унаследованных классов.

ответ

5

Проблема здесь состоит в том, что вы передаете указатель на элемент функции, которая полностью отличается от указателя на функцию, не являющегося членом (который является то, что ваша number функция принимает в качестве аргумента).

Вы можете использовать std::function и std::bind:

int number(std::function<int(int)> f) 
{ 
    return f(1); 
} 

... 

number(std::bind(&option1::timesTwo, this, _1)); 

Вы также можете использовать шаблоны, а также дополнительные аргументы, как

template<typename T> 
int number(T* object, int(T::*f)(int)) 
{ 
    return (object->*f)(1); 
} 

... 

number(this, &option1::timesTwo); 

Или просто (но не всегда правильно, в зависимости от ситуации и использования корпус): Сделать обратную функцию static:

static int timesTwo(int i){return 2*i;} 

Моя рекомендация состоит в том, что вы смотрите над раствором, используя std::function, потому что тогда это легко вызвать функцию number с любым типом вызываемого объекта, как лямбда:

number([](int x){ return x * 2; }); 
+0

Спасибо! Не могли бы вы продолжить, если я буду беспокоиться о решении просто добавить 'static'? Я понимаю, что использование 'std :: function' является более общим, но я уверен, что мне не придется вызывать функцию в каких-либо других обстоятельствах. – RobVerheyen

+1

@RobVerheyen Если передаваемая вами функция никогда не получит доступа к нестационарным членам в классе, в котором она определена, вы можете сделать ее «статической» без забот. –

4

Данная ошибка говорит:

error: reference to non-static member function must be called

Вы можете просто добавить static перед своими участниками.

И я предлагаю вам использовать std::function вместо функций указателя.

Рабочий код:

#include <iostream> 
#include <functional> 

struct base 
{ 
    base() {} 

    int number(std::function<int(int)> f) 
    { 
     return f(1); 
    } 
}; 

struct option1 : base 
{ 
    static int timesTwo(int i){return 2*i;} 
    option1() 
    { 
     std::cout << number(timesTwo); 
    } 
}; 

struct option2 : base 
{ 
    static int timesThree(int i){return 3*i;} 
    static int timesFour (int i){return 4*i;} 
    option2() 
    { 
     std::cout << number(timesThree); 
    } 
}; 

int main() 
{ 
    option1 a; // now it works 
} 
+0

Спасибо. Есть ли какая-либо причина, в частности, использовать «std :: function» над указателем, учитывая, что код, скорее всего, не понадобится ни одному из вышеперечисленных методов? – RobVerheyen

+1

@RobVerheyen Вы должны посмотреть [там] (http://stackoverflow.com/questions/25848690/should-i-use-stdfunction-or-a-function-pointer-in-c) и [там] (http : //stackoverflow.com/questions/9054774/difference-between-stdfunction-and-a-standard-function-pointer). Это больше C++ ish, но вы можете придерживаться своего решения. Я думаю, что более важно пересмотреть свой код. – coincoin

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