c++ - C++ 是否有定义的方法来传递指向类成员对象的成员函数的指针?
问题描述
假设我有一些功能:
void myFunction(void (MyClass::*function)(int), MyClass& myClass) {
(myClass.*function)(1);
}
这被称为如下:
class MyClass {
int value;
void setValue(int value) {
this->value = value;
}
}
MyClass myClass;
myFunction(&MyClass::set_value, myClass);
这个函数接受对象myClass
并调用它的成员函数setValue
,它调用它的参数设置为 1。
在我意识到 C++ 支持将成员函数作为参数传递之前,我已经手动设置我的代码以接收对象和函数指针,然后确定它们地址之间的偏移量。如果给定相同类型对象的不同实例,则可以保存此偏移量以调用相同的成员函数。
但是,是的,然后我发现你可以做到Class::*function
(我假设)完全按照我之前构建/描述的方式。
这导致了我的问题,假设我具有与以前相同的功能,除了我稍微改变了我的类结构:
class MyClass {
ChildClass childClass;
}
class ChildClass {
int value;
void setValue(int value) {
this->value = value;
}
}
那么在 C++ 中有没有办法将setValue
函数传递myFunction
给setValue
现在在ChildClass
对象内的给定函数MyClass
?
最明显的解决方案是添加一个setValue
成员函数,在其对象MyClass
中调用该函数,如下所示:setValue
childClass
class MyClass {
ChildClass childClass;
void setValue(int value) {
this->childClass.setValue(value);
}
}
class ChildClass {
int value;
void setValue(int value) {
this->value = value;
}
}
MyClass myClass;
myFunction(&MyClass::setValue, myClass);
但是,由于我正在研究的项目的语义,这不是一个理想的解决方案。因此,我很好奇是否有办法在 C++ 中实现这一点。如果没有,我当然可以手动实现它(它和以前一样,除了你要保存成员之间的偏移量childClass
和MyClass
以及成员和的偏移量setValue
)ChildClass
,但我自然想知道是否有是一种更“内置”的方式来实现这一点。
解决方案
鉴于 setValue 现在位于 MyClass 的 ChildClass 对象中,C++ 中是否有办法将 setValue 函数传递给 myFunction?
有一种方法是添加一个间接级别。该间接级别是多态函数包装器std::function
。myFunction
可以接受一个std::function
参数,该参数可以使用任意访问器函数进行初始化,包括 labdas。例如:
#include <functional>
struct ChildClass {
int value;
void setValue(int value) {
this->value = value;
}
};
struct MyClass {
ChildClass childClass;
};
void myFunction(std::function<void(MyClass&, int)> const& f, MyClass& myClass) {
f(myClass, 1);
}
int main() {
MyClass myClass;
myFunction([](MyClass& a, int b) { a.childClass.setValue(b); }, myClass);
}
使用std::function
您可以摆脱MyClass&
参数并期望用户提供std::function
由 lambda 表达式捕获的所需对象:
void myFunction2(std::function<void(int)> const& f) {
f(1);
}
int main() {
MyClass myClass;
myFunction2([&myClass](int b) { myClass.childClass.setValue(b); });
}
注意std::function
至少可以sizeof(void(Undefined_class::*member_pointer)())
在对象内部存储而不分配堆内存。C++ 标准没有要求,但是,这种优化的原因似乎是使用std::function
成员函数指针并不比直接使用成员函数指针差多少。或者,换句话说,如果您将代码中的成员和成员函数指针替换为std::function
,您的应用程序将不会因该†</sup>的额外内存分配而受到惩罚。在gcc
x86_64 上会产生 16 个字节的 inline 存储 in std::function
,它可以存储一个带有 2 个对象引用的 lambda 捕获对象。
†</sup> 的大小std::function
仍然比这大,而且它是一个非平凡的类型,所以它不能在寄存器中传递或返回。
推荐阅读
- javascript - Make the RBSheet reusable as a widget React-Native
- javascript - 尽管调用了函数,但全局变量在 JavaScript 中没有更新
- azure - ARM 模板 - '模板参数 JToken 类型无效。应为“字符串,Uri”。实际的“对象”
- javascript - 如何通过 ID 字段从存储在 Vuex 中的对象数组中获取项目?
- php - Dompdf-Laravel Unicode 字符无法正确呈现
- bash - “/bin/bash : - : Invalid option” 与 gitlab-CI 和 makefile 与 .ONESHELL
- rocket-chip - 构建火箭芯片工具时“bitbang_swd”的多重定义
- javascript - Angular - 带有窗口对象的 Twitter 直接消息在 Safari 中不起作用
- image - 使用 VueJs 复制或下载生成的 QR (vue-qrcode) 代码
- php - Facebook 刮板不读取 php 生成的元标记?