MFC和Qt优缺点(MFC⼏乎没有优点、全⾯下风)
在⽹上看到的,拿来和⼤家⼀起讨论下。
我曾经使⽤过来开发过软件,我想和⼤家分享我使⽤他们时所体会的不同之处。
我并⾮⼀个职业作家,这篇⽂章可能看起来不如专业的杂志和⽹站上的那么条理清晰。但是,我在这⾥是⽤我⾃⼰的语⾔来表达我⾃⼰的经验,希望能和你分享。英语⽐不是我的母语,所以可能会有⼀些⽤词古怪,词句错误之处,请发信给我,我可以改正他们。
本⽂不想假装客观公正,我只想表述我使⽤的经验。⽂中不会逐条的列举Qt和MFC各⾃的优缺点。我在使⽤MFC之前就已经使⽤Qt这个事实可能影响了我的客观性。
⽂章从实⽤主义的观点出发:我的⽼板给我⼀份软件的规划说明,并且让我来开发。其中⼀些我⽤Qt来开发,⽽另外⼀些我使⽤MFC来开发。
MFC(微软基础类库)是专门为windows设计的⼀个⽤于开发图形⽤户界⾯的类库。MFC或多或少使⽤了⾯向对象的⽅法包装了Win32的API,正因如此,这些API有时是C++,有时是C,甚⾄是C和C++的混合体。
Qt这个C++的图形库由Trolltech在1994年左右开发。它可以运⾏在Windows,Mac OS X, Unix,还有像Sharp Zaurus这类嵌⼊式系统中。Qt 是完全⾯向对象的。
Document/View model
MFC编程需要使⽤Document/View模式以及模板(template),如果不使⽤的话,编程将变得异常困难。⽽且,模板(template) 设定了固定的结构,若所需结构乃模板未定义之结构,则编程难已。例如,划分⼀区域使显⽰两个视图(view)于两个⽂档(document)。还有⼀个经常的问题是:模板(template)创建了视图(view)却⽆法访问(access)它,⽂档(document)要做完所有事情,但是这经常会出现问题。
Qt不强制使⽤任何设计模式。如果你认为恰当,使⽤Document/view没有任何问题。不使⽤也没有任何问题。
伪对象 vs 真对象
归根结底,Qt和MFC的差异在于其设计的差异。
MFC的根本⽬的是访问包装起来的⽤C语⾔写的windows的API。这绝⾮好的⾯向对象的设计模式,在很多地⽅,你必须提供⼀个包含15个成员的C语⾔的struct,但是其中只有⼀个与你所期望的相关,或者必须⽤旧式的参数来调⽤你的函数。
MFC还有许多让⼈摸不着头脑的地⽅,函数名没有任何的连续性。⽐如,如果你创建了⼀个graphical类,直到调⽤了creat()以后该类才会被创建。然⽽对dialogs,必须要等到OnInitDialog()才能创建这个对象。奇怪的是到了views,创建该类的函数名竟然成了 OnInitUpdate(),......你⾃⼰创建⼀个类⽤他们的⽅式调⽤它,你的程序崩溃了。
⽐如说有⼀个dialog包含CEdit控件,如果没有调⽤DoModal()你就不能使⽤GetWindowText()。否则将会莫名其妙的失败。总之,MFC充满了丈⼆和尚摸不着头脑的事情,并且,这种错误很难调试。
Qt恰恰相反,它的架构明显是经过精⼼设计的⾯向对象的。Qt因此在命名,继承,类的组织等⽅⾯保持了优秀的⼀致性。你只需要提供唯⼀⼀个⽅法的参数,仅此⼀个。在不同的类中调⽤⽅式也是有很强的连贯性。返回值也很有逻辑性。所有⼀切达到了简单和强⼤的和谐统⼀。⼀旦你使⽤了其中⼀个类,其他的类也就触类旁通,因为他们是⼀致的。
在Qt中可以利⽤Edit控件,⽤C++创建类的⽅法来创建⾃⼰的QLineEdit。永远可以马上访问任何的⽅法,不管它是显⽰还是隐藏。在这⾥没有迷局,⼀切都按照你认为的简单的⽅式来运作。
消息循环
MFC是事件驱动的架构。要执⾏任何操作,都必须是对特定的消息作出响应。Windows对应⽤程序发送的
信息数以千计,遗憾的是,要分清楚这些分繁芜杂的消息是很困难的,并且关于这⽅⾯的⽂档并不能很好的解决这些问题。
Qt的消息机制是建⽴在SIGNAL()发送和SLOT()接受的基础上的。这个机制是对象间建⽴联系的核⼼机制。利⽤SIGNAL()可以传递任何的参数。他的功能⾮常的强⼤。可以直接⼤传递信号给SLOT(),因此可以清楚的理解要发⽣的事情。⼀个类所发送的信号的数量通常⾮常的⼩(4或者5),并且⽂档也⾮常的齐全。这让你感觉到⼀切尽在掌握之中。SIGNAL/SLOT机制类似于Java中listener机制,不过这种机制更加轻量级,功能更齐全。
创建界⾯
MFC⽆法创建⼤⼩动态可变的⼦窗⼝,必须重新⼿动修改代码来改变窗⼝的位置(这恰好解释了为什么windows⾥的dialog是不可以改变的)这个问题在软件进⾏国际化翻译的时候更加严重,因为许多国家表达相同意思需要更长的词汇和句⼦,必须要对每个语⾔的版本重新修改⾃⼰的软件。
在Qt中,任何东西都可以⼿动的敲出来,因为它很简单:为了得到⼀个button,可以这样些
button = new PushButton( "buttonName", MyParentName );
如果想在按下某个按钮以后想调⽤某断代码的执⾏,可以这样写:
connect( button, SIGNAL( clicked() ), qApp, SLOT( action() ) );
Qt拥有⾮常简单⽽⼜不失强⼤的layout机制,以⾄于不使⽤它就是在浪费时间了。
Qt还提供了⼀个图形⽤户⼯具,Qt Designer,可以⽤来帮助建⽴⽤户界⾯。可以修改所使⽤的任何控件的属性。不⽤将他们放在严格的位置,可以通过layout完美的组织他们。这个⼯具所产⽣的代码我们是可以实际上阅读并且可以理解的。⽣成的代码单独放在⼀个⽂件⾥,在编程的同时,你可以随⼼所欲的多次重新⽣成⽤户界⾯。
Qt Designer可以让你完成许多在MFC中不可能完成的任务,⽐如⽤预先填好的⽣成listview,在每个tab上⽤不同的view来使⽤tab 控制。
帮助⽂档
qt listview
⽤户选择图形开发环境的时候,帮助⽂档是否周全是左右其选择的重要因素。Visual的开发环境的帮助⽂档MSDN(这个还要单独掏钱购买)⾮常的庞⼤,有10个CDROM光盘。他包罗万象,涵盖⼴泛。但是难免有泥沙俱下,主题模糊,关键信息不突出的遗憾。其链接设计的也很糟糕,通过链接很难从⼀个类跳转到其⽗类或者⼦类以及相关的类。如果你搜索⼀个关键字,不管是Visual C++, Visual J++, Visual Basic,只要包含这些关键字的信息统统的返回来。
Qt的⽂档设计的相当优秀。你可以到lltech上⾯⼀睹芳容。
Qt的⽂档完备且详细的覆盖了Qt的⽅⽅⾯⾯,竟然仅有18M。每⼀个类和⽅法都被详尽描述,巨细靡遗,举例充实。通过Trolltech公司提供的链接或者是Qt Assistant⼯具,可以⽅便的从⼀个类或者⽅法跳转到其他的类。⽂档还包含了⼀个初学者教程和⼀些典型应⽤的例⼦。同时还提供了FAQ和邮件列表,⽅便通过Internet或者⽤户来查阅。如果你购买了授权,在⼀天之内你将会得到Trolltech公司的技术⽀持。
实际上,Qt优秀的帮助⽂档使得寻求外部帮助的机会⼤⼤减少。Tolltech公司的⼀个宗旨是:有如此优秀的Qt产品以及其帮助⽂档,技术⽀持是多余的。
Unicode
使⽤MFC,如果要显⽰unicode,在编译链接的时候必须⽤到特殊的参数(和改变可执⾏⽂件执⾏的⼊⼝),必须在每个string前⾯加上T,将char修改成TCHAR,每个字符串处理函数(strcpy(), strdup(), strcat()...... )都要改变成另外的函数名。更令⼈恼⽕的是⽀持Unicode的软件竟然不能和不⽀持Unicode的DLL⼀起⼯作。当使⽤外部DLL来开发的时候这是个很严重的问题,但是你毫⽆选择。
使⽤Qt,字符串⽤QString来处理,其本⾝是与⽣俱来的Unicode.不需要改变什么东西。不要在编译/链接时候增添参数,不要修改代码,只需要使⽤QString就可以了。
QSting类功能强⼤,你可以⼴泛的使⽤它,并且不要担⼼Unicode问题。这使得转换为Unicode⾮常的⽅便。QSting提供了转换为char *和UTF8的函数。
显然,MFC的CString的设计相⽐于Qt的QString设计有着巨⼤的不同。CString以char *为基础提供了很少的功能。它的优点是当需要char *类型的时候,可以直接使⽤CString类型。乍看起来这个好像是个优点,其实实质上还是有很⼤的缺陷的,特别是可以直接修改char * ⽽不要更新类。在转变为Unicode的时候这个也碰到很⼤的⿇烦。
相反,QString在内部以unicode存储string,需要时提供char *功能。实际上很少⽤到char *,因为整个Qt的API⽤⽂本的⽅式响应QString 参数。QString还附带许多其他的功能,⽐如⾃动分享QString的内容。这是⼀个⾮常强⼤的类,你会喜欢在很多地⽅⽤它的。
国际化
使⽤MFC是可以国际化的,但是需要将每⼀个字符串放在⼀个字符串表中,在代码中到处使⽤LoadString(IDENTIFIET)。然后转化这些资源到DLL中,翻译字符串到所需要的语⾔,改变图形界⾯,然后调⽤程序使⽤这个DLL。整个过程是如此的繁琐,可谓牵⼀发⽽动全⾝。考虑的事情要⾯⾯俱到。
使⽤Qt的时候,只需要将字符串置于函数tr()中,在程序开发中这算是举⼿之劳。可以直接在代码中改变字符串的参考。Qt Linguist,Qt的⼀个⼯具,能够提取所有待翻译的string并按照友好的界⾯显⽰出来。这个⽤户界⾯⾮常适合翻译,使⽤字典,显⽰字符串内容,恰当的unicode 显⽰,快捷⽅式冲突检测,检测未翻译的字符串,检测字符串修改情况,功能齐全。这个软件可以供没有任何编程经验的翻译者使⽤。同时该软件在GPL的版权下发布,可以按照你的需求来修改它。
翻译以后的⽂档保存在XML中,适合软件复⽤的原则。为软件增加⼀种新的语⾔版本仅仅是⽤Qt Linguist产⽣⼀个新的⽂件⽽已。
resources问题
使⽤MFC,⼀部分开发过程要依靠“resources”,在很多的案例中开发者必须使⽤他们。这样会导致如下的后果:
出了Visual Studio,你很难使⽤其他的⼯具来完成开发。
资源编辑器仅有有限的功能,⽐如:通过Dialog编辑器不可能改变所有的属性,⼀些属性可以改变,另⼀些属性则不可能改变。(译者注:下⾯还有两条陈述MFC缺点的实例,但我感觉这些已经够说明问题了,暂时删节不译)
然⽽Qt并没有资源的概念,这就解决了以上所提到的问题。Qt提供了⼀个脚本使得能将编⼊你的代码。对于界⾯设计,Qt Designer则创建了可读的代码。
价格
⼀旦你购买了Visual Studio,你将免费的获得MFC SDK。
Qt在Unix上是可以免费获得其遵守GPL版权的版本(译者注:现在在windows 上也可以免费获得其GPL版本)。如果要开发不公开源代码的软件,必须购买Qt的授权。在特定平台下,每个开发者购买⼀个永久性授权,并获得⼀年的技术⽀持。(译者注:后⾯关于购买价格等问题删去,因为价格不固定,如果有疑问请到官⽅⽹站查询价格)
发布
在发布基于MFC的软件时,必须依靠存在于客户电脑上的MFC。但是这是不安全的,同样是MFC42.dll,可以基于相同的库得到3个不同的版本。通常,需要检查是否拥有正确的MFC42.dll版本,如果不是,就升级它。但是升级MFC42.dll会改变很多软件的⾏为。这让我感到很不舒服,如果⽤户在安装我的软件以后导致其机器死机该怎么办?
Qt则没有这个风险,因为Qt压根就没有“升级整个系统”这个概念。
感觉MFC相⽐QT的确有很多的不⾜,但MFC的⽤户巨⼤。Qt要想短时间撼动MFC的地位,还是有点难度的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。