我首先要提到的是,以下工作正常至Qt 5.0.0 beta 1(也许是beta 2和RC,也不知道),但在Qt 5.0.0最终版本中失败。我只想参考Qt 5.0.0最终版本中看到的结果。所以很可能这与Qt5最近的变化有关。
在C ++方面,我在命名空间中有一组类(QObject派生)(可选地用编译器标志触发;类在一个单独的库中,并且库将命名空间的使用留作了选项。图书馆的用户)。一个类Game
可能看起来像这样(摘录):
OAE_BEGIN_NAMESPACE
// forward-declarations:
class Player; // Player is just another class in the same library
class Game : public QObject
{
Q_OBJECT
public:
explicit Game(...);
public slots:
Player *player() const; // <-- the quesion is about such slots
};
OAE_END_NAMESPACE
宏OAE_BEGIN/END_NAMESPACE
扩展为namespace OAE_NAMESPACE {
... }
或者没有任何内容,就像Qt在<qglobal.h>
中所做的那样,只是将“QT”替换为“ OAE“在宏名称中:
#ifndef OAE_NAMESPACE
# define OAE_PREPEND_NAMESPACE(name) ::name
# define OAE_USE_NAMESPACE
# define OAE_BEGIN_NAMESPACE
# define OAE_END_NAMESPACE
# define OAE_BEGIN_INCLUDE_NAMESPACE
# define OAE_END_INCLUDE_NAMESPACE
# define OAE_BEGIN_MOC_NAMESPACE
# define OAE_END_MOC_NAMESPACE
# define OAE_FORWARD_DECLARE_CLASS(name) class name;
# define OAE_FORWARD_DECLARE_STRUCT(name) struct name;
# define OAE_MANGLE_NAMESPACE(name) name
#else /* user namespace */
# define OAE_PREPEND_NAMESPACE(name) ::OAE_NAMESPACE::name
# define OAE_USE_NAMESPACE using namespace ::OAE_NAMESPACE;
# define OAE_BEGIN_NAMESPACE namespace OAE_NAMESPACE {
# define OAE_END_NAMESPACE }
# define OAE_BEGIN_INCLUDE_NAMESPACE }
# define OAE_END_INCLUDE_NAMESPACE namespace OAE_NAMESPACE {
# define OAE_BEGIN_MOC_NAMESPACE OAE_USE_NAMESPACE
# define OAE_END_MOC_NAMESPACE
# define OAE_FORWARD_DECLARE_CLASS(name) \
OAE_BEGIN_NAMESPACE class name; OAE_END_NAMESPACE \
using OAE_PREPEND_NAMESPACE(name);
# define OAE_FORWARD_DECLARE_STRUCT(name) \
OAE_BEGIN_NAMESPACE struct name; OAE_END_NAMESPACE \
using OAE_PREPEND_NAMESPACE(name);
# define OAE_MANGLE_NAMESPACE0(x) x
# define OAE_MANGLE_NAMESPACE1(a, b) a##_##b
# define OAE_MANGLE_NAMESPACE2(a, b) OAE_MANGLE_NAMESPACE1(a,b)
# define OAE_MANGLE_NAMESPACE(name) OAE_MANGLE_NAMESPACE2( \
OAE_MANGLE_NAMESPACE0(name), OAE_MANGLE_NAMESPACE0(OAE_NAMESPACE))
namespace OAE_NAMESPACE {}
# ifndef OAE_BOOTSTRAPPED
# ifndef OAE_NO_USING_NAMESPACE
/*
This expands to a "using OAE_NAMESPACE" also in _header files_.
It is the only way the feature can be used without too much
pain, but if people _really_ do not want it they can add
DEFINES += OAE_NO_USING_NAMESPACE to their .pro files.
*/
OAE_USE_NAMESPACE
# endif
# endif
#endif /* user namespace */
在下文中,当说“启用命名空间”时,我的意思是我声明了宏OAE_NAMESPACE
,在这种情况下使用值oae
。
其中,我从QML中为我的应用程序的用户界面访问此类的实例和Player
返回的player()
类。为此,我按如下方式注册类:
qmlRegisterType<Game>();
qmlRegisterType<Player>();
我向QML前端提供指向Game
实例的指针,在QML中称为theGame
:
view.engine()->rootContext()->setContextProperty("theGame",
QVariant::fromValue<Game*>(game));
在QML中,我像往常一样使用它。一个小例子应该打印player()
:
Rectangle {
width: 100; height: 100
Component.onCompleted: console.log(theGame.player())
}
我得到以下结果,取决于我是否设置OAE_NAMESPACE
(顺便说一下:我对库和使用它的应用程序使用相同的设置):
当禁用命名空间时,一切都按预期工作 QML打印出指针:
Player(0x10b4ae0)
当启用命名空间(以及using
使用C ++代码时
库,所以我根本不更改代码),QML没有
了解Game::player()
的返回类型:
Error: Unknown method return type: Player*
将Game::player()
的返回类型更改为
oae::Player*
,一切正常:
oae::Player(0x10b4ae0)
到目前为止,我的结论是moc
没有考虑我在课堂上放置的命名空间。我的第一个猜测是:嘿,moc
不知道我在调用g++
时定义了命名空间,这就是我在.pro文件中所做的:
DEFINES += OAE_NAMESPACE=oae
但是,当将返回类型更改为OAE_NAMESPACE::Player*
时,它仍然有效,因此moc 知道OAE_NAMESPACE
宏,但它不会展开{ {1}}宏或它根本不解析名称空间。
OAE_BEGIN/END_NAMESPACE
为moc
生成以下“stringdata”,其中包含方法的返回类型:
当禁用命名空间并使用返回类型Player * Game::player() const
时:
Player*
当启用命名空间并使用返回类型"player\0Player*\0"
时:
Player*
当启用命名空间并使用返回类型"player\0Player*\0"
时:
OAE_NAMESPACE::Player*
另一方面,"player\0oae::Player*\0"
将moc
返回的类名添加到名称空间(如果已启用)。
我现在的结论是,只要在QObject元方法的签名中使用这些类型,我就可以通过编写QMetaObject::className()
而不是OAE_NAMESPACE::ClassName
来解决此问题。 (好吧,有更好的宏ClassName
)。因为这在代码中看起来很糟糕,对我来说它甚至看起来都是错误的,因为方法已经在命名空间中,是否有更好的解决方案?
现在还有OAE_PREPEND_NAMESPACE
(类似于OAE_BEGIN/END_MOC_NAMESPACE
), 所以我可能需要其他地方 ?我不知道它们在Qt中的使用位置和方式,所以我应该在我的库中相应地使用它们,因为我想使用与Qt相同的可选命名空间功能。
答案 0 :(得分:8)
它在5.0.0a中真的有效吗?
我浏览了Qt 5.0.0源代码并查看了解析方法的位置,特别是返回类型(fyi,5.0.0 \ qtbase \ src \ tools \ moc \ moc.cpp:L160)并且没有命名空间检查(两者都没有参数,所以player(Player* p)
也不会起作用)。
然而,它是为类def(5.0.0 \ qtbase \ src \ tools \ moc \ moc.cpp:L620&amp; L635)完成的
我认为“我们”可以将此称为错误(或疏忽)