引用对象方法
Reference to object method
我想引用对象方法的调用。这在 C++ 中可能吗?我应该搜索的技术名称是什么?我们可以提供一些具有预定值的参数吗?
下面的代码突出显示了我想使用的内容
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
Foo f;
auto& refToBarNoArgs = f.barNoArgs;
refToBarNoArgs(); // should call f.barNoArgs()
auto& refToBarMultArgs = f.barMultArgs(?, 3.14f, ?);
refToBarNoArgs(42, true); // should call f.barMultArgs(42, 3.14f, true)
What is the technical name I should be searching for?
这称为参数绑定,有时也称为部分函数
但首先,您应该知道您的两个示例都是完全相同的问题。毕竟,方法本质上是带有隐藏的第一个参数 this
的函数。
所以 refToBarNoArgs
是一个带 0 个参数的函数,它调用 Foo::barNoArgs
第一个参数 pre-populated。 refToBarNoArgs
是一个接受两个参数的函数,并使用第一个和第三个参数 pre-populated 调用 Foo::barMultArgs
,并使用自己的参数调用第二个和第四个。
这里的关键点是您的“引用”不能是 C++ 术语意义上的引用。引用实际上并不存在(因为没有与引用本身关联的对象)。在这两种情况下,我们都需要存储 pre-populated 参数的值,并管理它们的生命周期。它必须是一个实际的对象,具有存储和生命周期,并且表现得像一个函数。这称为 Functor.
该语言为我们提供了一点方便的语法糖,以方便同时创建此类仿函数的类型和单个实例:Lambdas。
auto refToBarNoArgs = [&f](){f.barNoArgs();};
refToBarNoArgs();
auto refToBarMultArgs = [&f](int i, bool b){f.barMultArgs(i, 3.14f, b);};
refToBarNoArgs(42, true);
如果您不熟悉 lambda,请注意我示例中的 [&f]
。这意味着 lambda 通过引用捕获 f
。正因为如此,它们的生存期(例如,存储在 std::function<>
中)不应超过 f
.
的生命周期
您也可以使用 std::bind
来获得同样的效果。事实上,最终结果与您的原始代码非常接近:
#include <functional>
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
int main() {
using namespace std::placeholders; // for _1, _2, _3...
Foo f;
auto refToBarNoArgs = std::bind(&Foo::barNoArgs, &f);
refToBarNoArgs();
auto refToBarMultArgs = std::bind(&Foo::barMultArgs, &f, _1, 3.14f, _2);
refToBarNoArgs(42, true);
}
就个人而言,我发现 lambda 更清晰。
从技术上讲,您可以获得指向成员函数的指针(成员函数指针),然后为对象调用该函数。
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
void foo() {
Foo f;
auto refToBarNoArgs = &Foo::barNoArgs;
(f.*refToBarNoArgs)();
}
修复(绑定)参数以创建一个新函数,然后您可以使用缺少的参数调用该函数更具挑战性。恕我直言,最简单的方法是使用 lambda 函数创建一个未命名的函数来包装成员并捕获对象。另一种方法是使用 std::bind
.
#include <functional> // for std::bind
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
void foo() {
using namespace std;
using namespace std::placeholders;
Foo f;
auto b = bind( &Foo::barMultArgs, f, _1, 3.14f, _2);
auto l = [&f](auto const& x, auto const& y) {return f.barMultArgs(x,3.14f,y);};
b(42, true); // should call f.barMultArgs(42, 3.14f, true)
l(42, true); // should call f.barMultArgs(42, 3.14f, true)
}
我想引用对象方法的调用。这在 C++ 中可能吗?我应该搜索的技术名称是什么?我们可以提供一些具有预定值的参数吗?
下面的代码突出显示了我想使用的内容
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
Foo f;
auto& refToBarNoArgs = f.barNoArgs;
refToBarNoArgs(); // should call f.barNoArgs()
auto& refToBarMultArgs = f.barMultArgs(?, 3.14f, ?);
refToBarNoArgs(42, true); // should call f.barMultArgs(42, 3.14f, true)
What is the technical name I should be searching for?
这称为参数绑定,有时也称为部分函数
但首先,您应该知道您的两个示例都是完全相同的问题。毕竟,方法本质上是带有隐藏的第一个参数 this
的函数。
所以 refToBarNoArgs
是一个带 0 个参数的函数,它调用 Foo::barNoArgs
第一个参数 pre-populated。 refToBarNoArgs
是一个接受两个参数的函数,并使用第一个和第三个参数 pre-populated 调用 Foo::barMultArgs
,并使用自己的参数调用第二个和第四个。
这里的关键点是您的“引用”不能是 C++ 术语意义上的引用。引用实际上并不存在(因为没有与引用本身关联的对象)。在这两种情况下,我们都需要存储 pre-populated 参数的值,并管理它们的生命周期。它必须是一个实际的对象,具有存储和生命周期,并且表现得像一个函数。这称为 Functor.
该语言为我们提供了一点方便的语法糖,以方便同时创建此类仿函数的类型和单个实例:Lambdas。
auto refToBarNoArgs = [&f](){f.barNoArgs();};
refToBarNoArgs();
auto refToBarMultArgs = [&f](int i, bool b){f.barMultArgs(i, 3.14f, b);};
refToBarNoArgs(42, true);
如果您不熟悉 lambda,请注意我示例中的 [&f]
。这意味着 lambda 通过引用捕获 f
。正因为如此,它们的生存期(例如,存储在 std::function<>
中)不应超过 f
.
您也可以使用 std::bind
来获得同样的效果。事实上,最终结果与您的原始代码非常接近:
#include <functional>
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
int main() {
using namespace std::placeholders; // for _1, _2, _3...
Foo f;
auto refToBarNoArgs = std::bind(&Foo::barNoArgs, &f);
refToBarNoArgs();
auto refToBarMultArgs = std::bind(&Foo::barMultArgs, &f, _1, 3.14f, _2);
refToBarNoArgs(42, true);
}
就个人而言,我发现 lambda 更清晰。
从技术上讲,您可以获得指向成员函数的指针(成员函数指针),然后为对象调用该函数。
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
void foo() {
Foo f;
auto refToBarNoArgs = &Foo::barNoArgs;
(f.*refToBarNoArgs)();
}
修复(绑定)参数以创建一个新函数,然后您可以使用缺少的参数调用该函数更具挑战性。恕我直言,最简单的方法是使用 lambda 函数创建一个未命名的函数来包装成员并捕获对象。另一种方法是使用 std::bind
.
#include <functional> // for std::bind
struct Foo {
void barNoArgs();
void barMultArgs(int, float, bool);
};
void foo() {
using namespace std;
using namespace std::placeholders;
Foo f;
auto b = bind( &Foo::barMultArgs, f, _1, 3.14f, _2);
auto l = [&f](auto const& x, auto const& y) {return f.barMultArgs(x,3.14f,y);};
b(42, true); // should call f.barMultArgs(42, 3.14f, true)
l(42, true); // should call f.barMultArgs(42, 3.14f, true)
}