- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我一直在寻找答案,但无济于事。我的感叹如下:
我有一个大致如下所示的 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/
我是一名优秀的程序员,十分优秀!