C++存储对对象自身函数的引用
C++ storing a reference to an objects own function
问题:
我正在尝试创建一种方法,根据C++类中用户给定的输入动态调用不同的函数。我尽量避免使用一堆if语句,因为这会给我的代码增加很多复杂性。我想做的是将引用存储在映射中,这样我就可以循环使用它并执行存储的函数。
当前设置:
目前我已经完成了这项工作,但它使用了静态方法调用,我不喜欢这种调用,因为我必须设置一堆对方法所需内容的静态引用,或者对私有变量进行大量getter。我陷入了静止的地狱。
这是一些代码(我身上没有实际的代码,所以我重写了我认为我有的代码。有些语法可能是错误的,但我有它在我的测试机上编译和工作(
typedef void (*functocall)(void) funcRef;
class Installer {
struct Step {
QString id,
QString message,
funcRef func
}
enum INSTALL_TYPE {
APP_INSTALL,
FILESYSTEM_INSTALL
BOTH_INSTALL,
...
}
public:
void addStep(QString id, QString message, funcRef func) {
Step step;
step.id = id;
step.message = message;
step.func = func;
}
void nextStep() {
// calls next in the map
m_steps[m_currStep].func();
m_currStep++;
}
void run(INSTALL_TYPE type) {
// Storing in a map lets me define the entire process for all install types in one method. Also can mix methods between processes if needed
// Also using steps to keep track of overall progess (currStep / m_steps.size())
// Also lets me show the user all of the steps that will occur for this install
// Basically is for creating a progress bar on a web interface and sending it percentages and a message
if(type == APP_INSTALL || type == BOTH_INSTALL)
{
addStep("upload", "Uploading files", &Installer::uploadAppFiles);
}
if(type == FILESYSTEM_INSTALL || type == BOTH_INSTALL)
{
addStep("upload", "Uploading files", &Installer::uploadFileSystemFiles);
addStep("extract", "Uploading files", &Installer::extractTar);
}
if(type == APP_INSTALL || type == BOTH_INSTALL)
{
addStep("install", "Install app", &Installer::installAppFiles);
}
if(type == FILESYSTEM_INSTALL || type == BOTH_INSTALL)
{
addStep("install", "Install file system", &Installer::installFileSystemFiles);
}
addStep("cleanup", "Cleanup system", &Installer::cleanup);
addStep("reboot", "Reboot system", &Installer::reboot);
}
static void uploadAppFiles() {
...
}
static void uploadFileSystemFiles() {
...
}
... other static methods
private:
QList<Step> m_steps;
int m_currStep;
}
首选解决方案:
我真正喜欢做的是在安装程序类中存储对非静态方法的引用。我只需要这个对象能够调用它自己的内部方法,这样我就可以确保这个对象永远存在。
我已经研究了std::函数,但无法使其工作,因为我没有c++11,我认为这是必需的我也不能使用boost::函数,因为我不想将boost添加到我的项目中。我已经在使用QT了,所以如果QT中有什么东西可以轻松做到这一点,我更喜欢它。
最初我是通过Javascript在客户端完成这一切的,这非常简单,我有点后悔把它移植到C++中,哈哈。
您只需要声明一个成员函数指针类型,该类型与普通函数指针具有不同的语法。此外,当通过成员函数指针调用成员函数时,显然必须提供对象。
//forward declare class
class Installer;
typedef void (Installer::*funcRef)(); // member function pointer
// ^^^^^^^^^ <-- mentions the class it is a member of
class Installer {
struct Step {
QString id;
QString message;
funcRef func; // member function
};
enum INSTALL_TYPE {
APP_INSTALL,
FILESYSTEM_INSTALL,
BOTH_INSTALL,
};
public:
void addStep(QString id, QString message, funcRef func) {
Step step;
step.id = id;
step.message = message;
step.func = func;
}
void nextStep() {
// supply objects to member function pointer call
// using this->*
(this->*m_steps[m_currStep].func)();
// ^^^^ <- supplies the object the member is to be called on
m_currStep++;
}
void run(INSTALL_TYPE type) {
// Storing in a map lets me define the entire process for all install types in one method. Also can mix methods between processes if needed
// Also using steps to keep track of overall progress (currStep / m_steps.size())
// Also lets me show the user all of the steps that will occur for this install
// Basically is for creating a progress bar on a web interface and sending it percentages and a message
if(type == APP_INSTALL || type == BOTH_INSTALL)
{
addStep("upload", "Uploading files", &Installer::uploadAppFiles);
}
if(type == FILESYSTEM_INSTALL || type == BOTH_INSTALL)
{
addStep("upload", "Uploading files", &Installer::uploadFileSystemFiles);
// addStep("extract", "Uploading files", &Installer::extractTar);
}
if(type == APP_INSTALL || type == BOTH_INSTALL)
{
// addStep("install", "Install app", &Installer::installAppFiles);
}
if(type == FILESYSTEM_INSTALL || type == BOTH_INSTALL)
{
// addStep("install", "Install file system", &Installer::installFileSystemFiles);
}
// addStep("cleanup", "Cleanup system", &Installer::cleanup);
// addStep("reboot", "Reboot system", &Installer::reboot);
}
void uploadAppFiles() {
// ...
}
void uploadFileSystemFiles() {
// ...
}
// ... other static methods
private:
QList<Step> m_steps;
int m_currStep;
};
如果从QObject派生类,并将需要调用的函数放入"slots"部分,则可以使用QMetaObject::invokeMethod
按名称调用它们。
相关文章:
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 类 Referention 中C++回调函数引用非静态函数
- 使用函数引用指向节点的指针删除链表中的节点?
- 解释通过从函数引用返回数组的语法
- "Class1"类"Class2"对象作为私有数据成员。如何通过"Class 2"函数引用"Class1"对象?
- 使用默认构造函数引用成员变量初始化错误
- 无法调用函数引用 c++
- 使用 decltype(this) 获取函数引用
- 我应该如何定义返回指针的函数?(引用指针与指针指针)
- 从内联函数引用文件静态变量
- Boost::将sigaction函数引用绑定到实例
- 一种比函数引用更有效的方法
- 奇怪的未定义函数引用,函数调用C++不存在
- 是否可以检测绑定成员函数引用的对象是否被删除或销毁
- 构造函数引用参数导致seg错误
- 是否可以使函数模板从函数引用中获取“decltype”
- 无法让 Lua 函数引用"self"
- 如何解析变量和函数引用(Linker & Compiler)?
- 从不同模块调用函数 - 引用错误
- 如何在主函数中连接到数据库,然后从其他函数引用它