如何通过插件机制在运行时动态加载数据类型

发布于 2025-01-03 12:05:59 字数 620 浏览 2 评论 0原文

由于 Qt 不允许在其插槽中使用模板,因此我尝试执行以下解决方案但没有成功。

首先,我想创建一个像这样的列表:

list commands = 
0, "MyDashboard", DashBoard0
1, "MomsDashboard", Dashboard1

仪表板 0 和 1 都源自小部件

假设您有一个 QListWidget,我们在其中添加列表中的字符串,然后进行连接:

connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), 
       this, SLOT(addDashboard(QListWidgetItem*)));

void addDashboard(QListWidgetItem* item) {
    int index = listWidget->row(item);

    QWidget* widget = new typeof(command.atIndex(index).getType());
    widget->show();

}

我将如何创建该列表并存储类型,就像在 C# 类型中所做的那样?

Since Qt doesnt allow templates in their slots, I tried to do the following solution without success.

First a would like to create a list like this:

list commands = 
0, "MyDashboard", DashBoard0
1, "MomsDashboard", Dashboard1

Dashboard 0 and 1 are both derived from widget

Lets say you have a QListWidget where we add the strings in the list and then do the connection:

connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), 
       this, SLOT(addDashboard(QListWidgetItem*)));

void addDashboard(QListWidgetItem* item) {
    int index = listWidget->row(item);

    QWidget* widget = new typeof(command.atIndex(index).getType());
    widget->show();

}

How would I create that list and store types just like you do in C# Type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

筱果果 2025-01-10 12:05:59

C++ 不允许您创建类型仅在运行时已知的对象(使用 new 运算符)。但是,您可以使用 工厂方法 模式的简化形式作为解决方法。

这是一个例子:

// Type IDs that are associated with a widget type
enum WidgetTypeId {
    dashboard1WidgetTypeId,
    dashboard2WidgetTypeId
};

// Factory method
QWidget* createWidget(WidgetTypeId type) {
    switch (type)
    {
        case dashboard1WidgetTypeId:
            return new DashBoard0;

        case dashboard2WidgetTypeId:
            return new DashBoard1;
    }
}

void addDashboard(QListWidgetItem* item) {
    int index = listWidget->row(item);

    QWidget* widget = createWidget(command.atIndex(index).getWidgetTypeId());
    widget->show();

}

我知道,不太漂亮。如果您的小部件是可克隆的,您可以使用 std::map 而不是丑陋的 switch 语句。这种替代方法是原型模式的一个示例。下面是一些示例代码,展示了这种方法:

class WidgetFactory
{
public:
    QWidget* create(const std::string& name) {
        return prototypes_[name]->clone();
    }

    void addPrototype(const std::string& name, QWidget* prototype) {
        prototypes_[name] = prototype;
    }

private:
    std::map<std::string, QWidget*> prototypes_;
}


WidgetFactory factory;
factory.addPrototype("DashBoard0", new DashBoard0);
factory.addPrototype("DashBoard1", new DashBoard1);


void addDashboard(QListWidgetItem* item) {
    int index = listWidget->row(item);

    QWidget* widget = factory.create(command.atIndex(index).getWidgetTypeName());
    widget->show();

}

C++ 不是一种非常动态的语言。它的 RTTI 功能有限,并且几乎没有 C# 中的反射功能。这就是为什么您必须求助于工厂方法和抽象工厂等模式。


附录

我还没有意识到 Qt 可能会提供超出 C++ 中通常可用的运行时类信息(我只将 Qt 用于简单的实用程序应用程序,所以我不知道所有的提示和信息)。该框架中可用的口哨)。考虑到这一点,我搜索并找到了这个邮件列表 讨论 关于如何通过类名实例化 Qt 对象。不过,我不知道该解决方案是否适用于插件对象。

C++ does not allow you to create an object (using the new operator) where the type is only known at runtime. However, you can use a simplified form of the Factory Method pattern as a workaround.

Here's an example:

// Type IDs that are associated with a widget type
enum WidgetTypeId {
    dashboard1WidgetTypeId,
    dashboard2WidgetTypeId
};

// Factory method
QWidget* createWidget(WidgetTypeId type) {
    switch (type)
    {
        case dashboard1WidgetTypeId:
            return new DashBoard0;

        case dashboard2WidgetTypeId:
            return new DashBoard1;
    }
}

void addDashboard(QListWidgetItem* item) {
    int index = listWidget->row(item);

    QWidget* widget = createWidget(command.atIndex(index).getWidgetTypeId());
    widget->show();

}

Not very pretty, I know. If your widgets are clonable, you can use a std::map instead of the ugly switch statement. This alternative approach would be an example of the Prototype Pattern. Here's some sample code showing this approach:

class WidgetFactory
{
public:
    QWidget* create(const std::string& name) {
        return prototypes_[name]->clone();
    }

    void addPrototype(const std::string& name, QWidget* prototype) {
        prototypes_[name] = prototype;
    }

private:
    std::map<std::string, QWidget*> prototypes_;
}


WidgetFactory factory;
factory.addPrototype("DashBoard0", new DashBoard0);
factory.addPrototype("DashBoard1", new DashBoard1);


void addDashboard(QListWidgetItem* item) {
    int index = listWidget->row(item);

    QWidget* widget = factory.create(command.atIndex(index).getWidgetTypeName());
    widget->show();

}

C++ is not a very dynamic language. It has limitied RTTI capabilities and practically none of the reflection features in C#. That's why you have to resort to patterns like Factory Method and Abstract Factory.


ADDENDUM

It hasn't dawned on me that Qt might provide runtime class information beyond what is normally available in C++ (I only used Qt for simple utility apps, so I don't know all the bells & whistles available in that framework). With that in mind, I searched and found this mailing list discussion on how to instantiate Qt objects by class name. I don't know if that solution works for plugin objects, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文