繁体   English   中英

Function 指向类成员 function

[英]Function pointers on a class's member function

void Parser::add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand)
{
    command_no_arg.push_back(comand);
    func_no_arg.push_back(f);
}

void Parser::prepare()
{
    //add_func_no_arg(Virtual_Machine::dump,"dump"); it work when i put it in static but i cant do that
    add_func_no_arg(vm.clear,"clear"); // ERROR HERE the vm.clear does not fit
}

我有这两个函数可以帮助我创建一个指针数组 func_no_arg; 我不能把虚拟机的函数放在 static 中; 为什么我不能在 function 上有一个指针,而它是一个对象中的“陷阱”? 可能是类型错误,这里是 some.hpp:

class Parser {
    public:
       /***/
        void prepare();
        void add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand);

    private:
        Virtual_Machine vm;
        std::vector<std::string> command_no_arg;
        std::vector<void (Virtual_Machine::*)()> func_no_arg;
        /***/

};


class Virtual_Machine {
    public:
      /***/
        void clear();
      /***/
}

编译器这样说:

Parser.cpp: In member function ‘void Parser::prepare()’:
Parser.cpp:65:36: error: invalid use of non-static member function ‘void Virtual_Machine::clear()’
     add_func_no_arg(vm.clear,"dump");
                                    ^
In file included from ../include/Parser.hpp:13,
                 from Parser.cpp:8:
../include/VM.hpp:23:14: note: declared here
         void clear();

获取成员指针的语法是&Virtual_Machine::clear (不是vm.clear ),并且可以使用.*运算符在Virtual_Machine的实例上调用这种类型的变量f (例如vm.*f() )。

或者,您可以编写&decltype(vm)::clear ,它不依赖于 class 名称。

正如 IlCapitano 所写,您必须使用特定的语法来处理指向成员的指针。 这是一个示例(使用g++ tmp.cpp -o tmp编译):

#include <iostream>
#include <string>
#include <vector>

class Virtual_Machine
{
    private:
        std::string name;

    public:
        Virtual_Machine(std::string n) : name(n) {}
        void clear() { std::cout << "Clear " << name << std::endl; }
};

class Parser
{
    private:
        Virtual_Machine vm;
        std::vector<std::string> command_no_arg;
        std::vector<void (Virtual_Machine::*)()> func_no_arg;

    public:
        Parser(std::string vm_name) : vm(vm_name) {}
        void add_func_no_arg(void (Virtual_Machine::* f)(), std::string command)
        {
            command_no_arg.push_back(command);
            func_no_arg.push_back(f);
        }
        void prepare()
        {
            add_func_no_arg(&Virtual_Machine::clear, "clear");
        }
        void test()
        {
            (vm.*(func_no_arg[0]))();
        }
};

int main()
{
    Parser a("vm_a"), b("vm_b");

    a.prepare();
    b.prepare();

    a.test();
    b.test();

    return 0;
}

程序的output为:

Clear vm_a
Clear vm_b

使用&Virtual_Machine::clear创建指向成员 function clear的 class Virtual_Machine实例的指针。 要稍后调用此 function,您必须使用运算符.*->*与运算符左侧的 class 的实例和指向 ZC1C425268E68385D1AB5074C17A94F1 右侧的指针(vm.*(func_no_arg[0]))() 如果 function 有参数,您可以将它们放在最右边的一对括号中。

如上所述,获取指向成员函数的指针的正确语法是&Class::member 这背后的一般想法是,当您声明 class 时,每个 function 和 class 都属于以 ZABB4A2F2A29DCZC0 命名的命名空间。 因此,获取指向成员 function 的指针的语法实际上等同于指向命名空间内的 function 的任何指针。 请记住,当尝试在 class 中检索指向 function 的指针时,访问说明符仍然适用。

但是,有一个很大的区别,当你声明一个成员 function 时,会添加一个隐式参数(c++ 中的this ),你实际上已经注意到了,这就是为什么类型是return_type (Class::*) (parameters)

有两种方法可以处理这个问题。 第一个,正如其他人所说,当您需要调用 function 时,使用.* or ->*语法(点或箭头用于访问实例“内部”,星号)取消引用 function 指针)。 另一种方法(主要是如果您不关心 object,或者在调用它时无法访问它)是将 function 包装在std::function和 9 中,通过绑定任何“隐式this和 9”“A”您需要的参数,使用std::bind 通过将std::functionstd::bind一起使用,您将能够使用您习惯的 c 样式语法。

cppreference 上std::functionstd::bind的示例部分显示了如何实现这一点

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM