为Qt注册自定义类型时,何时,何地以及为什么使用名称空间 [英] When, where and why use namespace when registering custom types for Qt

查看:712
本文介绍了为Qt注册自定义类型时,何时,何地以及为什么使用名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相似的问题已经多次提出,但我主要关注名称空间和指针问题.

Similar questions have been raised multiple times, but I'm focussing on the namespace and pointer issues.

MyClass.h

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

fooMyClass.cpp(这么多排列):

fooMyClass.cpp (so many permutations):

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>();
}

所以我的问题是,如果我打算将自定义对象用于命名空间内部和外部的信号和插槽(可能用作引用和指针),那么何时以及为什么需要提供命名空间和/或指针变体.我是否总是必须完全限定名称空间?

So my question is, when and why is it required to provide the namespace and/or the pointer variant if I intend to use the custom objects for signals and slots (potentially as reference and pointer) inside as well as outside the namespace. Do I always have to fully qualify the namespace?

推荐答案

在此答案中,我指的是Qt5. Qt4不适用于这种用例.

I'm referring to Qt5 in this answer. Qt4 doesn't go well with this use case.

如果仅打算在信号和插槽中使用它,则不需要数据流运算符.如果要进行序列化,则必须使用它们.

Data stream operators are not required for your type if you only intend to use it in signals and slots. They are required if you want to do some serialization.

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

Qt considers MyClass and MyClass* two different unrelated types. You should declare, register and use them separately. Using const MyClass & argument type is compatible with MyClass in Qt meta-object system. Note that using MyClass and MyClass* meta types simultaneously in one program is unusual and can cause mistakes and confusion. You should choose one of the options and use it throughout the program. Also passing pointers to slots is not recommended because it causes unsolvable ownership problem. So I recommend to use passing by const reference (which sometimes will be converted to passing by value internally in Qt signal-slot system). If MyClass objects contain massive data, you should implement implicit data sharing using QSharedDataPointer.

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

First of all, you always need to declare your meta type:

Q_DECLARE_METATYPE(foo::MyClass)

它在编译时有效,因此您对类的引用方式没有限制.以下代码也可以正常工作:

It works at compile time, so there are no limitations on how you refer to your class. The following code will work as well:

using namespace foo;
Q_DECLARE_METATYPE(MyClass)

注册元类型

现在,您需要注册课程.从理论上讲,您需要指定要用于引用类型的所有字符串,即:

Registering a meta type

Now you need to register your classes. Theoretically, you need to specify all strings that you want to use to refer to your type, i.e.:

qRegisterMetaType<foo::MyClass>("MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");

在模板参数中如何引用MyClass都无关紧要.以下代码将类似地工作:

It doesn't matter how you refer to MyClass in the template argument. The following code will work similarly:

using namespace foo;
qRegisterMetaType<MyClass>("MyClass");
qRegisterMetaType<MyClass>("foo::MyClass");

例如,当您引用信号和SIGNAL(signal1(MyClass))之类的插槽时,"MyClass""foo::MyClass"字符串用于标识参数类型.

For example, the "MyClass" and "foo::MyClass" strings are used to identify argument types when you refer to your signals and slots like SIGNAL(signal1(MyClass)).

如果您使用带有成员函数指针的新信号槽语法,则只需使用任意字符串参数进行一次注册.似乎打算使它即使没有任何注册也可以工作. 这部分文档指示仅在Q_DECLARE_METATYPE中添加与相反,而该则需要qRegisterMetaType().不幸的是,现在在我的Qt安装中,它仅适用于直接连接.排队的连接仍然需要至少一个注册呼叫.

If you using new signal slot syntax with pointers to member functions, you need to do only one registration with arbitrary string argument. It seems that it is intended to make it work even without any registrations. This part of the docs instructs to only add Q_DECLARE_METATYPE, in opposite to this that requires qRegisterMetaType(). Unfortunately, now in my Qt installation it works only with direct connections. Queued connections still require at least one registration call.

我在Qt 5.1中尝试了一些注册变体,发现Qt自动注册了没有名称空间的别名.因此,如果您写

I was experimenting with some variants of registration in Qt 5.1 and found out that Qt automatically registers aliases without namespace. So if you write

qRegisterMetaType<foo::MyClass>("foo::MyClass");

,Qt将另外自动注册"MyClass"别名.因此,执行完此语句后,您将可以将您的类型称为MyClassfoo::MyClass.文档中没有有关Qt如何处理名称空间的信息.我们可以假设这种行为是有意的,在下一版本中不会删除,但我不会依赖于此.以下代码使隐式注册变得显而易见:

, Qt will additionally automatically register "MyClass" alias. So, after executing this statement you will be able to refer to your type as MyClass and foo::MyClass. There is no information in the documentation about how Qt handles namespaces. We could assume that this behavior is intended and will not be removed in next versions but I wouldn't rely on that. The following code makes implicit registration obvious:

qRegisterMetaType<foo::MyClass>("foo::MyClass");
qRegisterMetaType<bar::MyClass>("MyClass");

Qt 5.1说:

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

QMetaType::registerTypedef: Binary compatibility break -- Type name 'MyClass' previously registered as typedef of 'MyClass' [1030], now registering as typedef of 'bar::MyClass' [1032].

Qt 4.8可以正常运行(此版本似乎尚未引入此行为).

Qt 4.8 works without error (it seems that this behavior is not yet introduced in this version).

这篇关于为Qt注册自定义类型时,何时,何地以及为什么使用名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆