今天在看QT对象内存管理的一篇文章时:
http://blog.csdn.net/dbzhang800/article/details/6300025
想到了一个问题。
就是QT类库体系结构与Delphi类库体系结构的对比问题。
Delphi的TApplication->TComponent->TPersistent->TObject
QT的QApplication->QCoreApplication->QObject
注意,它直接继承自QObject,而省略了delphi的两个层次:TComponent和TPersistent
因此特意查看了一下,QObject已经包括了setParent,非常类似于TComponent的InsertComponent(owner)
QObject的setObjectName相当于TComponent的setName。这样一来,QObject即已经包括了TComponent的主要功能。
但是QObject貌似没有TPersistent的RTTI和流入流出的功能。不过不要紧,因为C++标准里就包括了RTTI和流入流出的功能,因此不需要在类库里体现这一点,而是随时随地可用的。而Delphi因为自成一体,语言和类库结合的过于紧密,不得不单独定义一层TPersistent来提供相应的功能(也就是说,不使用VCL的object pascal是没有RTTI和流入流出功能的)。
这么说来,一个QObject就已经包括了Delphi的TObject、TPersistent和TComponent这三个类层次的功能。并且QObject还多了对signal的管理,tr的功能。
让我觉得最有趣的就是,QT也有一个Application,并且相当于也是继承自TComponent。
那么接下去呢?Delphi单独写了一个TControl,主要目的是给图形类也提供一些鼠标处理的功能和文字字体颜色对齐这些基本的显示功能(比如用户可点击TLabel),这是Delphi非常独特和强大的功能。而QT接下去就是QWidget,相当于把TControl和TWinControl的功能直接合并了,QLabel就是继承自它的,这样一来每个QWidget都有句柄(问题:为啥Spy++探测不到QT程序的每个子元素),有了句柄还不是可以随心所欲的做各种处理,这就和标准Windows控件没有什么区别了。
那么QT的图像显示类怎么处理?基本上是自成一体,查看一下QPaintDevice是原类(不继承自任何类),这时C++的多继承特性就可发挥作用了,QWidget直接继承自QObject和QPaintDevice,即把Delphi的TWinControl和TGraphicControl的功能强行融合在一起(因为多继承的原因,这种融合是轻而易举的),准确的说,是把Delphi的TCustomControl和TGraphic的功能强行融合在一起,并且对图像控件和非图像控件不做区分,即每个QWidget子类都可自绘,而不依赖于系统提供的原生控件的功能与界面。
再进一步说,无论QT还是Delphi,首先它的是一个GUI元素(有没有句柄则不一定),它才可以具备自绘功能。但是如何自绘,以及哪些功能是通用的,这就需要一个单独的类进行定义,而不可能直接放到QWidget和TGraphicControl里,此时QT的QPaintDevice和Delphi的TGraphic就扮演了这种功能。不同之处在于QPaintDevice是原类,而TGraphic却仍继承了TObject和TPersistent,前面说过了TPersistent的功能,QPaintDevice也有(尽管它是原类),但继承自TObject并获取它提供的功能感觉不是很必要,也许这是Delphi基于RAD的设计的原因——为了管理和使用上的方便,因此才这样规定所有类都必须继承TObject。TGraphic还必须实现TInterface, IStreamPersist两个接口,说明还提供了引用计数和随心所欲的流入流出(TPersistent是针对DFM文件格式的)。
最后一个问题,QT为什么没有Delphi里对应的TForm?目前的情况是QMainWindow对应Delphi的主TForm,它继承自QWidget,相当于把控件专门强化后专门用来做主界面。而QApplication则与TApplication严格对应,都是为了把程序全局管理功能集中到Application,甚至application.run与app.exec都是那么的一致,哈哈。而QT的每一个QWidget,都可作为一个显示窗口(除了主Form以外的每一个TForm),因此不需要单独定义TForm对应的组件,换而言之QWidget提供的功能过于强大,每一个QWidget既可以自己作为窗口,也可作为窗口的一个子元素。
QWidget过于强大,看看这些函数就知道了,大概QT官方是想尽可能的提供最方便的全部界面功能:
setGraphicsEffect
setMask
setStyle
windowModality
setWindowRole
而Delphi尽管也异常强大,但也没有直接提供如此之多的功能,更多的还是要基于Winapi的特性来扩展相应的功能。其实QT这么做也是没有办法呀。Delphi控件在取得Windows句柄后可以有winapi随时来助阵,但QT一切都是自绘,如果它官方不提供这种基本的特殊功能(好像有点绕口),普通程序员是很难进行扩充的。
还有TScreen,还有QDialog,还有。。。以后再补充。
还有一个重大的区别,就是Delphi只使用了绝对坐标体系,而QT同时使用了Layout可变的相对坐标体系(其实Delphi最新的FMX体系也提供了类似的layout)和setGeometry绝对坐标体系,还有QSS也能控制一部分界面排版,这也导致我在开发的时候经常产生一些困惑。
最后提一句,体系结构类的函数多不要紧,那个完全不占内存,只有类里的数据成员才会增加对象的内存大小。
------------------------------------------------------------------------------
总的来说,QT的体系结构与Delphi类库体系结构十分相似,没有什么本质区别,但是鉴于Delphi严格区分图像控件和非图像控件,说明管理的更精细一些,把TForm与普通控件区分开也是这个原因,节省系统资源。而Delphi强调TComponent,除了提供父子控件的内存管理功能以外,还方便对非可视的算法与系统功能也可制作控件,也算是它的一大特色。