类似的问题已多次提出,但我专注于命名空间和指针问题.
MyClass.h
namespace foo {
class MyClass {
MyClass();
};
QDataStream &operator<<(QDataStream &out, const MyClass & myObj);
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
} // namespace foo
Q_DECLARE_METATYPE(foo::MyClass) // #1
Q_DECLARE_METATYPE(foo::MyClass*) // #2
Run Code Online (Sandbox Code Playgroud)
fooMyClass.cpp(这么多的排列):
MyClass::MyClass()
{
qRegisterMetaType<MyClass>("MyClass"); // #3
qRegisterMetaType<MyClass*>("MyClass*"); // #4
qRegisterMetaType<MyClass>("foo::MyClass"); // #5
qRegisterMetaType<MyClass*>("foo::MyClass*"); // #6
qRegisterMetaType<foo::MyClass>("foo::MyClass"); // #7
qRegisterMetaType<foo::MyClass*>("foo::MyClass*"); // #8
qRegisterMetaType<MyClass>(); // #9
qRegisterMetaType<MyClass*>(); // #10
qRegisterMetaType<foo::MyClass>(); // #11
qRegisterMetaType<foo::MyClass*>(); // #12
// same for qRegisterMetaTypeStreamOperators<T>();
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,如果我打算在命名空间内部和外部使用信号和槽(可能作为引用和指针)的自定义对象,那么何时以及为什么需要提供命名空间和/或指针变量.我是否总是要完全限定名称空间?
Pav*_*hov 21
我在这个答案中指的是Qt5.Qt4与这个用例不相符.
如果您只打算在信号和插槽中使用数据流运算符,则不需要数据流运算符.如果要进行某些序列化,则需要它们.
Qt考虑MyClass和MyClass*两种不同的不相关类型.您应该单独申报,注册和使用它们.使用const MyClass &参数类型与MyClassQt元对象系统兼容.请注意,在一个程序中同时使用MyClass和MyClass*元类型是不常见的,可能会导致错误和混淆.您应该选择其中一个选项并在整个程序中使用它.还不建议将指针传递给插槽,因为它会导致无法解决的所有权问题.所以我建议使用传递const引用(有时会在Qt信号槽系统内部转换为值传递).如果MyClass对象包含海量数据,则应使用隐式数据共享实现QSharedDataPointer.
首先,您始终需要声明您的元类型:
Q_DECLARE_METATYPE(foo::MyClass)
Run Code Online (Sandbox Code Playgroud)
它在编译时工作,因此对你如何引用你的课程没有限制.以下代码也可以使用:
using namespace foo;
Q_DECLARE_METATYPE(MyClass)
Run Code Online (Sandbox Code Playgroud)
现在你需要注册你的课程.从理论上讲,您需要指定要用于引用类型的所有字符串,即:
qRegisterMetaType<foo::MyClass>("MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");
Run Code Online (Sandbox Code Playgroud)
MyClass在模板参数中引用并不重要.以下代码将类似地工作:
using namespace foo;
qRegisterMetaType<MyClass>("MyClass");
qRegisterMetaType<MyClass>("foo::MyClass");
Run Code Online (Sandbox Code Playgroud)
例如,当您引用信号和插槽时,"MyClass"和"foo::MyClass"字符串用于标识参数类型SIGNAL(signal1(MyClass)).
如果使用带有成员函数指针的新信号槽语法,则只需要使用任意字符串参数进行一次注册.似乎即使没有任何注册也可以使其工作.该文档的这部分指示只会增加Q_DECLARE_METATYPE相反,对这种需要qRegisterMetaType().不幸的是,现在在我的Qt安装中它只适用于直接连接.排队连接仍需要至少一次注册调用.
我在Qt 5.1中尝试了一些注册变体,发现Qt会自动注册没有命名空间的别名.所以,如果你写
qRegisterMetaType<foo::MyClass>("foo::MyClass");
Run Code Online (Sandbox Code Playgroud)
,Qt还会自动注册"MyClass"别名.因此,执行此语句后,您将能够将您的类型称为MyClass和foo::MyClass.文档中没有关于Qt如何处理命名空间的信息.我们可以假设这种行为是有意的,不会在下一版本中删除,但我不会依赖它.以下代码使隐式注册变得明显:
qRegisterMetaType<foo::MyClass>("foo::MyClass");
qRegisterMetaType<bar::MyClass>("MyClass");
Run Code Online (Sandbox Code Playgroud)
Qt 5.1说:
QMetaType :: registerTypedef:二进制兼容性break - 类型名称'MyClass'以前注册为'MyClass'的typedef [1030],现在注册为'bar :: MyClass'的typedef [1032].
Qt 4.8工作没有错误(似乎这个行为尚未在此版本中引入).
| 归档时间: |
|
| 查看次数: |
3445 次 |
| 最近记录: |