2015-01-07 5 views
0

Win 7 Cygwin GCC 4.8.3 -std = гну ++ 11Как передать функцию в качестве параметра

Я исследовал это на StackOverflow и cplusplus и подумал, что я принял функцию как параметр правильно, даже «изящно», но ясно, что я что-то не понял. Может ли кто-нибудь объяснить, как правильно передать функцию в качестве аргумента, и почему то, что у меня есть, не будет работать?

Предусмотрено одно предупреждение для прототипа и единственная ошибка для вызова. Изменение genX в genY в комментариях, но как genX, так и genY имеют одинаковые предупреждения/ошибки.

class MyClass { 
    typedef double (*func_t)(double sum); 
    void driver(); 
    double genX(func_t fnc) { }; 
    double genY(double (*funct)(double sum)) { }; 
    // note: no known conversion for argument 1 from 
    // '<unresolved overloaded function type>' to 
    // MyClass::func_t {aka double (*)(double)} 
    double myThingie(double sum) { }; 
}; 

void MyClass::driver() { 
    genX(myThingie); 
    genY(myThingie); 
    // no matching function for call to 'MyClass::genX(<unresolved overloaded function type>)' 
} 

ответ

4

"Can anyone explain how to pass a function as an argument correctly, and why what I have won't work?"

Вам нужно

typedef double (MyClass::*func_t)(double sum); 
      // ^^^^^^^^ 

объявить указатели на функции для функций класса член.

И получить их адрес, как

genX(&MyClass::myThingie); 
genY(&MyClass::myThingie); 
0

Если вы настаиваете на прохождение (C-подобный, не являющегося членом) указатель на функцию, использовать (в частности, для удобства чтения) в typedef (за пределами class) объявить его подпись:

typedef double func_sig_t(double); 

затем передать указатель на это, например

double genX(func_sig_t* fnc) { }; 

Однако, я хотел бы использовать std::function

double genX(std::function<double(double)>); 

это менее дешево, но вы могли бы пройти замыкание лямбда, например, звоните

double t; 
    double f = genX([=t](double x){return x+t;}); 

Или вы хотите, чтобы передать указатель на функций членов? У них разные синтаксисы!

+0

Я думаю, что этот ответ не сразу ответить на вопрос. Проблема в том, что функция Op передается, поскольку аргумент является методом экземпляра и имеет неявный первый параметр –

1

В ваших заявлениях указывается, что функции ожидают указатели функций, не указатели на функцию. Во-вторых, вы предоставляете указатели на функции myThingie, который является функцией-членом от MyClass, не предоставляя экземпляр. Читайте на указателе функции C или, если можете, используйте std::function для более C++-ish-решения.

1

Попробуйте следующее

class MyClass { 
    typedef double (MyClass::*func_t)(double sum); 
    void driver(); 
    double genX(func_t fnc) { }; 
    double genY(double (MyClass::*funct)(double sum)) { }; 
    // note: no known conversion for argument 1 from 
    // '<unresolved overloaded function type>' to 
    // MyClass::func_t {aka double (*)(double)} 
    double myThingie(double sum) { }; 
}; 

void MyClass::driver() { 
    genX(&MyClass::myThingie); 
    genY(&MyClass::myThingie); 
    // no matching function for call to 'MyClass::genX(<unresolved overloaded function type>)' 
} 
+0

Он работает (как и ожидалось), но myThingie имеет область действия MyClass и должен быть видимым внутри драйвера. Зачем мне нужна дополнительная ссылка? И для исходного typedef, так как он ограничен внутри MyClass, не должно быть достаточной ссылки на бонусные функции, а использование функции * * для области вне MyClass будет более корректной? Или это просто C++? –

+0

@Arthur Schwarez Следующее сообщение об ошибке GCC объясняет проблему «ошибка: ISO C++ запрещает принимать адрес неквалифицированной или не поставленной в скобки функции нестатического члена для формирования указателя на функцию-член. Say '& MyClass :: myThingie' –

0

myThingie функция член - указатель на него имеет тип double (MyClass::*)(double).
«Указатель на член» полностью отличается от обычного указателя и нуждается в экземпляре подходящего класса, из которого он может быть разыменован.

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

class MyClass { 
    typedef double (*func_t)(double sum); 
    void driver(); 
    double genX(func_t fnc) { }; 
    double genY(double (*funct)(double sum)) { }; 
}; 

double myThingie(double sum) { }; 

или настроить типы:

class MyClass { 
    typedef double (MyClass::*func_t)(double sum); 
    double genX(func_t fnc) { }; 
    double genY(double (MyClass::*funct)(double sum)) { }; 
    double myThingie(double sum) { }; 
}; 

void MyClass::driver() { 
    genX(&MyClass::myThingie); // The "MyClass::" is important here, too. 
    genY(&MyClass::myThingie); 
} 

В этом случае вы должны использовать " синтаксис разыменования «указатель-к-член» для вызова функции.
Например,

double genX(func_t fnc) { return (this->*fnc)(0.0) }; 
Смежные вопросы