存储在类中的函数指针

时间:2018-10-21 23:50:12

标签: c++ c++11

我希望能够在struct或class中存储函数的指针,那么当按下按钮时可以调用该函数吗?这就是我所拥有的:

struct INFO
{
    std::function<int(int, int)> call_back;
};

class YO
{
public:
    YO() {};
    ~YO() {};

    int SUM(int A, int B) { return A + B; }
};

int main()
{
    //std::function<int(int, int)> datFunc = SUM;
    INFO info;
    YO* yo = new YO();
    info.call_back = yo->SUM;

    //std::function<int(int, int)> func =;
    std::cout << info.call_back(10, 10) << std::endl;

    system("pause");
    return 0;
}

我收到错误消息:

Error   C3867   'YO::SUM': non-standard syntax; use '&' to create a pointer to member   FunctionPointertest 
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion) FunctionPointertest 

3 个答案:

答案 0 :(得分:1)

在这种情况下,您还需要向函数调用提供主机对象的实例。 std :: function支持此功能,它可以执行许多转换,但是原型变为

auth.requires_membership

当您调用它时:

std::function<int(YO*, int, int)> call_back;

答案 1 :(得分:0)

一些选项可以满足您的需求。使用lambda是最好的解决方案。

void func() {
    INFO info;
    YO yo;
    YO* yo2 = new YO;
    info.call_back = [&yo](int a, int b) {
        return yo.SUM(a, b);
    };
    using namespace std::placeholders;
    info.call_back = std::bind(&YO::SUM, std::ref(yo), _1, _2);
    info.call_back = std::bind(&YO::SUM, yo2, _1, _2);
}

P.S。您通常不想在c ++中使用new

答案 2 :(得分:0)

这是Variadic Template Classes的集合,如果您有C++17可用,则可以轻松完成此操作。第一类仅存储任何类型的std::function的通用版本!第二类通过member function存储第一类,并且将registerfunction pointerfunction objectlambda member function存储。它还有另一个invoke。在此示例中,我目前正在使用lambdas。我有两个lambdas,第一个1 st 接受两个int类型,将它们相加并返回int,如您在上面的问题中所述。 2 nd 将两个std::strings连接起来,然后将它们打印到屏幕上,但不返回任何值。您甚至可以通过将std::vector<Functor<>>存储在驱动程序类中来扩展它。 register_callback在将其推入向量中时会略有变化,并且call_back您可以选​​择。您可以一次全部调用它们,也可以通过索引值进行搜索以调用特定的索引,但是我将其作为练习留给您。

#include <string>
#include <iostream>
#include <functional>

template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
    std::function<RES_TYPE( ARG_TYPES... )> func_;
};

template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
    Functor<RES_TYPE, ARG_TYPES...> functor;

public:
    Driver() = default;
    ~Driver() = default;

    void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
        functor = func;
    }

    RES_TYPE call_back( ARG_TYPES... args ) {
        return functor.func_( std::forward<ARG_TYPES>(args)... );
    }    
};    

int main() {
    // Function Type: int ( int, int );
    Functor<int, int, int> func;
    auto lambda = []( int a, int b ) { return a + b; };
    func.func_ = lambda;

    Driver<int, int, int> driver;
    driver.register_callback( func );
    int a = 3;
    int b = 5;
    std::cout << driver.call_back( a, b ) << '\n';
    std::cout << driver.call_back( 7, 5 ) << '\n';

    // Function Type: void ( string, string );
    Functor<void, std::string, std::string> func2;
    auto lambda2 = []( std::string str1, std::string str2 ) {
        str1 = str1 + " " + str2;
        std::cout << str1 << '\n';
    };

    Driver <void, std::string, std::string> driver2;
    func2.func_ = lambda2;
    driver2.register_callback( func2 );
    std::string str1 = "Hello";
    std::string str2 = "World";
    driver2.call_back( str1, str2 );
    driver2.call_back( "Generic", "Programming" );

    return 0;
}

输出为:

8
12
Hello World
Generic Programming

如果您在此处注意到此代码;无需弄乱指针或动态内存。通过为我们使用std::function和类的默认dtors可以解决所有这些问题。

我尽了最大的努力来设计这种具有简单性,可读性的产品,同时使其尽可能地便携和通用。我相信可以进行一些改进,但是我认为这符合您的要求。