gpt4 book ai didi

c++ - 对成员函数使用 std::function

转载 作者:行者123 更新时间:2023-11-30 03:53:26 24 4
gpt4 key购买 nike

我的问题是关于使用 std::function 来对方法进行分类。假设我有以下类层次结构:

class Foo {
public:
virtual void print() {
cout << "In Foo::print()" << endl;
}

virtual void print(int) {
cout << "In Foo::print(int)" << endl;
}
};

class Bar : public Foo {
public:
virtual void print() override {
cout << "In Bar::print()" << endl;
}

virtual void print(int) override {
cout << "In Bar::print(int)" << endl;
}
}

现在有另一个函数应该根据其输入动态调用两个类方法之一:

void call(Foo* foo, void (Foo::*func)(void)) {
(foo->*func)();
}

Foo* foo = new Foo();
Bar* bar = new Bar();
call(foo, &Foo::print);
call(bar, &Foo::print);

当我使用 g++/clang++ 编译上面的代码片段时,它按预期工作,输出为:

In Foo::print()
In Bar::print()

我的问题是:

  1. 由于有两个同名函数(重载):print,当我传递类函数的地址:&Foo::print时,编译器怎么知道我是实际上调用了 Foo::print(void) 而不是 Foo::print(int)

  2. 是否有另一种方法可以概括上面的代码,以便 void call(Foo*, xxx) 的第二个参数可以同时使用 Foo::print 传递(void)Foo::print(int)

  3. 是否可以使用 C++11 std::function 中的新功能来实现此功能?我知道为了将 std::function 与非静态类方法一起使用,我必须使用 std::bind 将每个类方法与特定类绑定(bind)对象,但这对我来说效率太低,因为我有很多类对象要绑定(bind)。

最佳答案

Since there are two functions (overloaded) with the same name: print, when I pass the address of class function: &Foo::print, how did the compiler knows that I am actually calling Foo::print(void) but not Foo::print(int)?

这是允许的,因为 [over.over]/p1:

A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set.

编译器可以使用参数类型列表的目标类型来确定指向成员的指针引用重载集中的哪个函数:

A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts. The function selected is the one whose type is identical to the function type of the target type required in the context. [ Note: .. ] The target can be

     — an object or reference being initialized (8.5, 8.5.3, 8.5.4),
     — the left side of an assignment (5.18),
     — a parameter of a function (5.2.2),
     — [..]

名称 Foo:print 代表一个重载集,编译器通过它查找匹配项。目标类型 Foo::print(void) 存在于重载集中,因此编译器将名称解析为该重载。

Is there another way that I can generalize the code above such that the second parameter of void call(Foo*, xxx) can be passed using both Foo::print(void) and Foo::print(int)

没有通用的方法来使用名称本身。该名称必须解析为重载。相反,尝试更改代码以接受像 lambda 这样的函数对象:

template<class Callable>
void call(Foo* foo, Callable&& callback) {
callback(foo);
}

int main()
{
call(foo, [] (Foo* f) { f->print(); f->print(1); });
}

关于c++ - 对成员函数使用 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30130803/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com