C ++存储对象自己的函数

时间:2016-08-25 23:32:53

标签: c++ qt function progress-bar

问题

我尝试创建一种方法,根据用户在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 ++哈哈。

2 个答案:

答案 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按名称调用它们。