QT对C++进行了扩展,提供了三个主要的功能:信号槽、运行时类型信息和动态属性,这三个扩展功能都是由“元对象系统”提供的。
成都创新互联专注于双城企业网站建设,响应式网站,电子商务商城网站建设。双城网站建设公司,为双城等地区提供建站服务。全流程专业公司,专业设计,全程项目跟踪,成都创新互联专业和态度为您提供的服务元对象系统基于三个支撑点:
1 OObject为需要使用元对象系统有点的类提供了基类。
2 Q_OBJECT宏声明在类的私有段中,可用来启用元对象特征,如动态属性,信号槽。
3 元对象编译器(moc)为每一个QObject子类提供了实现元对象特征的必要代码。
MOC工具读取C++源代码。如果它发现一个或者多个类的声明包括了宏Q_OBJECT,它产生另一个C++源代码文件,这个文件中包含了含有宏Q_OBJCET类的元对象代码。这个新产生的源文件或者被包含值类的源文件中或者,或者更通常的是被编译和链接到类的的实现中。
元对象系统除了提供信号和槽机制(介绍元对象系统的主要原因),还提供如下特征:
1 QObject::metaObject()返回了类关联的元对象;
2 QMetaObjcet::className()在运行时返回字符串形式的类名称,不需要通过C++编译器的原始运行时类型信息支持。
3 QObject::inherits()方法返回一个对象是否是QObject类或者QObject子类的实例。
4 QObject::tr()和Qobject::trUtf8()用来完成国际化;
5 QObject::SetProperty()和QObject::property()通过名称动态的设置和获取属性;
6 QMetaObject::newInstance()构造类的新实例。
对QObject类也可以使用动态转换qobject_cast(),qobject_cast()函数与标准C++dynamic_cast()的行为很像,优点是不需要RTTI支持,并且它可以跨动态库边界。qobject_cast()尝试将它的参数转换到特定的指针类型,如果对象是正确的类型(在运行时判断)返回非0指针,如果不兼容则返回0。
看下面的例子。我们假设MyWidget继承了Qwidget并且声明了宏Q_OBJECT:
QObject *obj = new MyWidget;
变量Obj是QObject类型,实际引用到一个MyWidget对象,所以我们可以转换:
QWidget *widget = qobject_cast
从QObject到QWidget的转换是成功的,因为obj实际上就是一个MyWidget,是Qwidget的子类。现在我们知道obj是一个MyWidget对象,我们可以转换到MyWidget *:
MyWidget *myWidget = qobject_cast
到MyWidget的转换也是成功的,因为qobject_cast()对待QT内建类型和自定义类型之间没有区别的。
下面的转换则是失败的:
QLabel *label = qobject_cast
obj到Qlabel的转换是失败的。label也被设置为0。
这种运行时类型信息机制可以在运行时处理不同类型的对象,比如:
if (QLabel *label = qobject_cast(obj)) { label->setText(tr("Ping")); } else if (QPushButton *button = qobject_cast (obj)) { button->setText(tr("Pong!")); }
当然也可以使用QObject做为基类却不使用Q_OBJECT宏,这样的类就没有了元对象代码,前文提到的信号槽和其他特征也就都失效了。从元对象系统的观点来看,一个不使用元代码QObject子类等效于它最近的使用元对象代码的祖先。这就意味着,QMetaObject::className() 将会返回祖先的类名而不是实际类的名字。
因此强烈建议大家,所有QObject的子类都使用Q_OBJECT宏,无论是否使用了信号槽和动态属性。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。