gpt4 book ai didi

c++ - 如何在从 QObject 派生的类上正确使用 qRegisterMetaType?

转载 作者:IT老高 更新时间:2023-10-28 21:34:10 25 4
gpt4 key购买 nike

我一直在寻找答案,但无济于事。我的感叹如下:

我有一个大致如下所示的 ClassA:

class ClassA : public QObject {
Q_OBJECT
public:
ClassA() { mName = "lol"; }
~ClassA();
void ShowName() { std::cout << mName << std::endl; }
std::string mName;
};

当然,由于我使用的是moc,所以这个类在我的项目中实际上分为cpp和hpp,但这部分不是这里的问题。

请注意,我没有故意使用 Q_DECLARE_METATYPE,因为我现在实际上并不需要它的功能(QVariant 扩展)。我只关心运行时实例化。

这里的问题是 Q_OBJECT 禁止复制和赋值构造函数。因此,我必须将 qRegisterMetaType 应用到 ClassA 本身,而是应用到 ClassA* 乍一看似乎工作正常。

现在,我想在运行时从一个字符串动态创建这个类并运行方法 ShowName()。我这样做是这样的:

int main() {
qRegisterMetaType<ClassA*>("ClassA*");

int id = QMetaType::type("ClassA*");
std::cout << "meta id: " << id << std::endl; // Outputs correct generated user id (not 0)

ClassA* myclass = static_cast<ClassA*>(QMetaType::construct(id));
myclass->ShowName(); // Segfaults, oh dear

return 0;
}

现在,有我的问题。我似乎实际上没有正确构造的对象。

如果我们将类更改为如下所示:

class ClassA : public QObject {
Q_OBJECT
public:
ClassA() { mName = "lol"; }
ClassA(const ClassA& other) { assert(false && "DONT EVER USE THIS"); }
~ClassA();
void ShowName() { std::cout << mName << std::endl; }
std::string mName;
};

然后我们可以相应地将我们的程序更改为:

int main() {
qRegisterMetaType<ClassA>("ClassA");

int id = QMetaType::type("ClassA");
std::cout << "meta id: " << id << std::endl; // Outputs correct generated user id (not 0)

ClassA* myclass = static_cast<ClassA*>(QMetaType::construct(id));
myclass->ShowName(); // "lol", yay

return 0;
}

显然我可以只使用我的假覆盖复制构造函数,但感觉不对,Qt 建议反对,而是建议仅使用指向 QObjects 的指针。

有人看到这里出了什么问题吗?另外,我知道关于 SO 也有类似的问题,但没有一个能解决这个确切的问题。

最佳答案

一些事情:

  • 注册 ClassA* 不起作用的原因是您对construct() 的调用正在构造指向ClassA 对象的指针,而不是实际对象。

  • 值得注意的是 QMetaType 文档中的以下引用:

Any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered.

  • 看看Qt对qMetaTypeConstructHelper的实现:

    template <typename T>
    void *qMetaTypeConstructHelper(const T *t)
    {
    if (!t)
    return new T();
    return new T(*static_cast<const T*>(t));
    }

并注意他们对复制构造函数的使用。在这种情况下,您有两种解决问题的方法:

1) 提供一个拷贝构造函数(你已经完成了)

2) 提供不使用复制构造函数的 qMetaTypeConstructHelper 特化:

template <>
void *qMetaTypeConstructHelper<ClassA>(const ClassA *)
{
return new ClassA();
}

关于c++ - 如何在从 QObject 派生的类上正确使用 qRegisterMetaType?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7872578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com