Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
注册Qt的自定义类型时何时、何地以及为什么使用命名空间_Qt_Namespaces - Fatal编程技术网

注册Qt的自定义类型时何时、何地以及为什么使用命名空间

注册Qt的自定义类型时何时、何地以及为什么使用命名空间,qt,namespaces,Qt,Namespaces,类似的问题已经被多次提出,但我将重点放在名称空间和指针问题上 MyClass.h namespace foo { class MyClass { MyClass(); }; QDataStream &operator<<(QDataStream &out, const MyClass & myObj); QDataStream &operator>>(QDataStream &in, MyClass &myObj);

类似的问题已经被多次提出,但我将重点放在名称空间和指针问题上

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
名称空间foo{
类MyClass{
MyClass();
};
QDataStream和操作员(QDataStream和in、MyClass和myObj);
}//名称空间foo
Q_DECLARE_元类型(foo::MyClass)/#1
Q_DECLARE_元类型(foo::MyClass*)/#2
fooMyClass.cpp(如此多的排列):

MyClass::MyClass()
{
qRegisterMetaType(“MyClass”);/#3
qRegisterMetaType(“MyClass*”);/#4
qRegisterMetaType(“foo::MyClass”);/#5
qRegisterMetaType(“foo::MyClass*”);/#6
qRegisterMetaType(“foo::MyClass”);/#7
qRegisterMetaType(“foo::MyClass*”);/#8
qRegisterMetaType();/#9
qRegisterMetaType();/#10
qRegisterMetaType();/#11
qRegisterMetaType();/#12
//qRegisterMetaTypeStreamOperators()也一样;
}

因此,我的问题是,如果我打算在名称空间内外为信号和插槽(可能作为引用和指针)使用自定义对象,那么何时以及为什么需要提供名称空间和/或指针变量。我总是必须完全限定名称空间吗?

我在这个答案中指的是Qt5。Qt4不适合这个用例

数据流运算符 如果只打算在信号和插槽中使用数据流运算符,则类型不需要数据流运算符。如果要执行某些序列化,则需要使用它们

指针、引用和值 Qt考虑了
MyClass
MyClass*
两种不同的不相关类型。您应该单独声明、注册和使用它们。使用
constmyclass&
参数类型与Qt元对象系统中的
MyClass
兼容。请注意,在一个程序中同时使用
MyClass
MyClass*
元类型是不寻常的,可能会导致错误和混淆。您应该选择其中一个选项,并在整个程序中使用它。另外,不建议将指针传递到插槽,因为这会导致无法解决的所有权问题。因此,我建议使用passing by const引用(有时会在Qt信号槽系统内部转换为passing by value)。如果
MyClass
对象包含大量数据,则应使用
QSharedDataPointer
实现隐式数据共享

声明元类型 首先,您始终需要声明元类型:

Q_DECLARE_METATYPE(foo::MyClass)
它在编译时工作,因此对如何引用类没有限制。以下代码也可以使用:

using namespace foo;
Q_DECLARE_METATYPE(MyClass)
注册元类型 现在您需要注册您的类。理论上,您需要指定要用于引用类型的所有字符串,即:

qRegisterMetaType<foo::MyClass>("MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");
例如,
“MyClass”
“foo::MyClass”
字符串用于在引用信号和插槽时识别参数类型,如
信号(信号1(MyClass))

新的信号和插槽语法 如果使用指向成员函数的指针的新信号槽语法,则只需使用任意字符串参数进行一次注册。看来,它的目的是让它工作,即使没有任何注册。指示仅添加
Q\u DECLARE\u元类型
,与要求的
qRegisterMetaType()
相反。不幸的是,现在在我的Qt安装中,它只适用于直接连接。排队连接仍然需要至少一个注册呼叫

无命名空间类的隐式注册 我在Qt5.1中试验了一些注册变体,发现Qt自动注册别名而不使用名称空间。所以如果你写

qRegisterMetaType<foo::MyClass>("foo::MyClass");
Qt 5.1说:

QMetaType::registerTypedef:二进制兼容性中断--类型名称“MyClass”以前注册为“MyClass”[1030]的typedef,现在注册为“bar::MyClass”[1032]的typedef

Qt 4.8工作正常(似乎此版本中尚未引入此行为)。

您的答案确实权威!您还可以添加一些关于嵌套类的注释吗?我经常使用
struct XyzService{struct Result{…};Result doWork(…);}
当我使用
qRegisterMetaType(“XyzService::Result”)
注册
XyzService::Result
时,我会看到关于信号插槽连接的未注册类型的警告。但是,
“结果”
工作正常。当然,这将导致多个嵌套的
Result
类型(具有不同的外部类)的命名冲突<代码>:(
using namespace foo;
qRegisterMetaType<MyClass>("MyClass");
qRegisterMetaType<MyClass>("foo::MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");
qRegisterMetaType<bar::MyClass>("MyClass");