问题:
我尝试创建一种方法,根据用户在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 :: function但是无法将其作为我没有c ++ 11 我认为是必需的吗? 我也不能使用boost :: function ,因为我不想为我的项目添加提升。我已经在使用QT,所以如果QT中的某些东西可以轻松地做到这一点我宁愿这样做。
最初我在客户端通过Javascript完成所有这一切,这非常容易,我有点后悔将它转移到C ++哈哈。
答案 0 :(得分:0)
您只需要声明一个成员函数指针类型,它与普通函数指针的语法不同。当你通过成员函数指针调用成员函数时,你显然必须提供对象。
//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;
};
答案 1 :(得分:0)
如果您从QObject派生您的类并将您需要调用的函数放入&#34; slot&#34;部分,然后您可以使用QMetaObject::invokeMethod
按名称调用它们。