●写在本文之前
  算起来,我用Visual C++也有将近5年的历史了。在这期间,我也曾涉猎过Visual Basic和Delphi,但都是浅尝而止;Visual C++始终是我的主业。可是努力的成果如何呢?我用Delphi作出了十多个有规模的软件,用VB--虽然我用在VB上的时间只有短短的两三个月--也有两个像样的项目;然而,在我付出了最大热情和最多努力的Visual C++上面,却只作出了三个自己看得上眼的软件。
  固然,在用Visual C++的时候,MFC帮了我不少的忙。但是,在写下这个题目之时,我就已经打定主意:在这篇文章中,只对MFC提出批评,不说MFC的好话。Visual C++的拥护者且慢发难,听我道出其中原因。我注意到,象候捷先生这样对MFC极其热爱的著者,在其大著《深入浅出MFC》中对MFC的评价也是尽量的做到客观和公允;而大师Charles Petzold和Jeff Prosise,在他们的作品中也只是给予MFC以谨慎的赞美。Charles Petzold还很客气的指出了MFC的局限。然而另外一些编程书籍的作者,特别是某些国内的作者,似乎毫不吝惜把最华丽的语言和最夸张的赞美赋予MFC,从书架上任意翻开一本介绍Visual C++的书籍,看看它的前言和序章,往往充斥着让人目眩的溢美之辞。多少初学者被这些充满暗示和诱导的辞令吸引,以为MFC是完全可视化的,象VB一样容易掌握的东西,当他们深入以后,会不会有上当的感觉呢?我痛恨一切不负责任的夸大和炫耀,特别是只为了增加书籍销量而不惜昧着良心说话的作者,而我的感觉是现在这样的作者和书籍似乎已经泛滥了。本着矫枉必须过正的指导思想,我的目的很明确,就是要批评MFC。对Visual C++和MFC非常熟悉的读者,我无虑您对本文提出批评和指责,因为您对MFC已经有了自己的观点,不会为我所误导;对Visual C++的入门者,我希望您在听够了对Visual C++和MFC的赞美之后,来听听另一种声音,即使它并不完全正确(甚或是充满谬误),至少能让您带着自己的思想来看待您将要学习的东西。●对MFC的批判之一:不支持属性,MFC凭什么同其他语言抗衡?
  窃以为在编程语言中引入“Property”的概念是在面向对象的编程思想后最为重大的革新之一。其实,目前市场上绝大部分编程语言,包括VB,Delphi,C++Builder和PowerBuilder等等都支持Property。程序员只要简单的修改对象的属性,就能够完成相当部分的工作,不仅是减少了无谓的劳动,更重要的是减少了出错的机会,并且使得生成更复杂的界面和完成更复杂的工作成为相对容易的工作。我想绝大部分人会同意,如果去掉了Property这个东西,那么象VB和Delphi这样好的RAD,包括Microsoft一直倡导的ActiveX,都会失去了绝大部分的魅力。这个道理,Microsoft应该是在推出Visual Basic 1.0的时候就认识到了。可是自从Visual C++诞生到现在,它似乎丝毫没有使用Property的意思,虽然Visual C++这个名字在很大程序上沾了它的长兄Visual Basic的光,不过它并没有从VB那里学到如何让编程更简单和更轻松的秘诀。
  有人可能会说,data member of class不是property吗?不是的,如果你用过C++Builder的话你一定能明白这种分别。MFC从来就不支持Property,而且今后看来也不会了,这意味着用MFC,你还是得干苦力活。(ActiveX?不错,ActiveX支持Property,而且MFC支持ActiveX开发,不过这并不是三段论发挥作用的地方。)●对MFC的批判之二:单调的处理方式使本来应该简单的工作变得复杂
  应该没有人反对这样的观点:用Visual C++开发界面,特别是不符合Microsoft所谓“标准”的程序,比VB,Delphi或是C++Builder都要慢得多。(附带说一句,我不知道Microsoft制定Windows Logo标准,并且要求程序员遵守的依据是什么;我自己的程序99%以上都不符合这个标准。)可这是为什么呢?是C++语言在这方面的天生不足?肯定不是。
  在我看来,罪魁祸首是MFC中的CDocTemplate,这个类规定了一种非常死板和机械的机制,即一个Document,一个View和一个FrameWnd绑定在一起。遗憾的是,实际情况往往复杂的多。对界面稍微稍微要求高一点的程序大多要求一个Document有多个View,甚至在某些程序中,希望在同一个View中显示多个Document的内容:比如,将两个公司的业绩放在一起作比较。对View和FrameWnd的关系也有类似的情况。然而,DocTemplate的机制使得这样并不高的要求变的相当困难。想实现你的要求吗?可以。你要添加新的View类。你要从默认的IDR_MAINFRAME复制资源到新的类中。你要用AddDocTemplate添加自定义模板。你要用GetFirstDocTemplatePosition和GetNextDocTemplate检索模板列表。你要用GetDocString察看每个模板是否符合你的要求。你要重载CFrameWnd::OnCreateClient以派生新的视图。你要用CView::SetDlgCtrlID和CFrameWnd::SetActiveView以及CFrameWnd::RecalcLayout来在各个视图中切换。你要用未公开的CDocManager管理文档模板。你要...还要吗?反正我是怕了。●对MFC的批判之三:固步自封,不思进取
  MFC可以作为固步自封的活教材。别忘了,MFC是和Borland OWL同一时代的产物(还有多少人记得OWL呢?)当然,这不是MFC的错误。不过,如果以个类库的体系自从2.0版本以来就没有丝毫改变,是不是意味着这个类库已经臻于完美了呢?不,即使Microsoft也不敢这么狂妄。但事实是,MFC的体系从MFC2.0以来就没有变动过。每个版本的更新,不过是增加了一些新类,某些类的接口稍作修改,仅此而已。不,不要把ATL作为MFC的改进;ATL从来就不依赖于MFC。
  谁都知道在这几年中C++语言有了多么大的改进。包括RTTI,Dynamic Creation,Exception,Standard Template Library等等都成为新的C++标准的一部分。不过,Microsoft好像并不喜欢这些新东西,它的做法是另起炉灶;于是在同以套Visual C++中就出现了两套互不兼容的实现。平心而论,在新的C++标准出台前,Microsoft自己实现这些机制实在是一个相当了不起的创举;但是历史总是在发展的,MFC为什么不从善如流,尽量利用语言中已经实现的功能,而非要固执的用自己的一套老办法?事实上,MFC几乎没有用到新的C++方案中任何有益的元素--尽管这些方案已经对MFC库中很多问题提出了相当完美而且精练的解决方法。
●对MFC的批判之四:天然的倾向性
  不知道您对AppWizard生成的默认项目有什么感觉。反正我的感觉是:这种工程就是用来开发象Word,Excel这样的程序的。好像MFC天然的就倾向于这样一种程序。但事实上,这种程序少之又少。
  在Microsoft看来,好像每个程序都应该有一个File菜单,而且这个菜单下面一定应该有New,Open,Save,Exit这些选项。在我的实际经验来说,我只搞过一个程序符合这样的要求。有多少人真的要搞一个自己的字处理程序或是电子表格呢?对于很多常见的、基于数据库的程序,你需要New,Open和Save吗?如果是基于网络的程序呢?特别是在多媒体程序和游戏程序中,MFC生成的框架与其说是帮助,不如说是累赘。
  这倒是符合Microsoft的一贯风格:你要的只是特定的功能,它却一并塞给你一大串不相干的东西,并且在很多时候,这些不相干的东西反而成为麻烦制造者。于是,我不得不在新生成一个项目后,不辞劳苦的去掉AppWizard“慷慨”的赠送品,包括大量无用的菜单和工具条按钮,然后才能开始实际的工作。说实在的,AppWizard在为我减少工作量的同时,也增加了我不少劳动量。
  MFC定义了一个Document-View框架,并且把Document定义的相当宽泛,几乎可以代表任何数据。但是在实现上,Document是相当狭窄的;比如Document定义的Serialize固定的与一个CArchive对象联系在一起,而CArchive又固定的与一个CFile联系在一起,这样实际上就限定Document处理的对象只能是磁盘文件。况且,在一个Serialize中处理所有数据的序列化也是一种相当机械而死板的机制:它只能处理小量而且是一次处理完毕的数据,而实际上,程序往往要处理大块的数据,并且不可能一次完成。在这种情况下,CDocument的处理机制反而是个障碍。此外,在很多类型的程序中,CDocument扮演的是一个很尴尬的角色:比如在绝大部分数据库程序中,CDocument完全是个鸡肋,实际的数据处理只能靠CRecordset来完成;再比如说,在最典型的Doc-View程序--就是记事本程序--中,CDocument根本是个无能的东西,因为它存取数据反而要求助于CEditView::SerializeRaw。
  Doc-View框架有可能突破这些限制吗?完全可能。不过,你要有心理准备,如果你要这么作,你就必须求助于一大堆的未公开函数和类型,这些东西完全没有文档,依赖于你对MFC“底下的东西”究竟有多么熟悉,以及你是否愿意钻研MFC的源代码--在绝大多数情况下这不是一件愉快的工作。如果你使用这些未公开的东西出了问题,或者你不知道如何使用,对不起,Microsoft不会给你任何支持--谁教你不按照Microsoft的逻辑工作来着!
●对MFC的批判之五:什么是封装?
  好像这不成为一个问题。但是对MFC而言,封装的定义是不成立的。这句话的意思是说,如果你不想生产玩具的话,如果你需要调试程序的话,如果你的代码需要有比AppWizard更多的东西,那么,MFC对你来说就不是封装的。如果你的程序运行出了错,对不起,问题不在你的代码里面,而在MFC库的某个文件中,Visual C++会为你打开这个文件,至于“为什么会出错?”“这个函数究竟是用来干什么的?”MFC不会给你答案,你自求多福吧。如果你除了MSDN中的公开文档以外,对MFC的源代码从不关心,那么恭喜你,你是个快乐的程序员,但是你永远不能生产出真正有用的程序。
  候捷先生在其著作《深入浅出MFC》中也曾提到:或许有人会产生疑问,追寻“黑盒子底下的东西”,岂不有违面向对象编程的初衷?但是没有办法,不去熟悉MFC的源代码,永远只能生产玩具。候先生说的很委婉,尽量不批评MFC。但是,我可以这样说:使用VB,Delphi,C++Builder,Java这些语言的程序员几乎从来不去关心类库的源代码,可是这些语言并不是用来生产玩具的!

解决方案 »

  1.   

    stopped reading after this line
    不支持属性,MFC凭什么同其他语言抗衡?
    MFC is not a language.
      

  2.   

    MFC做界面累死个人,DELPHI简的多。
      

  3.   

    delphi做界面是挺快。但bug挺多的。出了问题就很麻烦,会让你郁闷死.
      

  4.   

    delphi的问题是好,而不够好,用多了就知道了。
      

  5.   

    mfc的问题是烦琐, 但许多东西可以自己控制, 
    delphi的问题是, 东西都给你做好了,但是还不够好, 有时候你想完善下,自己发挥下,
    结果出了问题,够你受的, 还难摆平.
    还是觉得mfc好一些, 学的不敢说深入,也觉得它烦琐, 但脉络清晰些.归根到底, sdk最好, ..很无奈.
      

  6.   

    恩。。以前用的是CB,后来学VC后发现,各有千秋吧。。虽然VC支持的property不多,但是也正因为限定不多,所以想自定义编写一些控件比较容易,如果是CB的话,想设置一个自定义风格的控件相对会难很多吧。因为限定的太多了。。
      

  7.   

    mfc用的好坏,很大程度上取决于win32 sdk的水平。
      

  8.   

    ●对MFC的批判之一:不支持属性,MFC凭什么同其他语言抗衡?
    这个不能怪MFC,要怪你只能怪C++
    这让我想起前一段时间的"C++之死",如果上面也算MFC的不足的话,你完全可以批判C的没有面向对象●对MFC的批判之二:单调的处理方式使本来应该简单的工作变得复杂
    一个文档可以对应多个视,反之亦然●对MFC的批判之三:固步自封,不思进取
    大部分的框架都是在上面增加功能,而不是从头来过
    MFC也是,从最初的对win32 SDK的封装,到后面对数据库的支持,对编写COM的支持,对Socket的支持,都是MFC的改进●对MFC的批判之四:天然的倾向性
    你完全可以不用这个框架
    并且你可以用VS编写自己的框架模板●对MFC的批判之五:什么是封装?
    你用Release的形式调试代码,应该不会进入到MFC的源代码了
    而且有的时候通过MFC的源代码,你才能知道你的问题在那里
    毕竟MFC过了这么多年,还是有很多人在用,虽然他也有很多不尽人意的地方
    但是毕竟没有楼主说的那样不名一文
      

  9.   

    看来搂主用VC并不多 从文中看应该只是生成过一些SDI的框架 因为搂主甚至不知道MFC向导的step1有一项 Dialog based
      

  10.   

    楼上的搞笑~MFC用好了,跟SDK差不多的.
    人家没做那么死,从任何一个层次面上,都给了你机会去介入,加以控制.总体来说,MFC还是不错的.
    从使用的角度,它是一个很好的类库,安全,稳定,方便...从学习的角度,它的源码,它的架构,它的文档,都是教科书似的东西了.
      

  11.   

    有写东西也不能全怪MFC啊 毕竟人家只是一个库 
    DELPHI做界面是好 不过BUG也很多的
      

  12.   

    MFC的好在于它的包容,它对SDK进行了简单的封装,你可以选择用或者不用,有成千上万的C++库可以让你使用在MFC的框架之中。当然MFC肯定有不尽人意的地方,但是没有什么是完美的,正如我们每个人一样。没有能力去改变它就要去适应它,没有能力适应它那就要抛弃它,人类的大脑是用来创造的,如果一定要在鸡蛋里挑骨头,那是自讨没趣楼主的内容写的还不错,只是批判的标题掺杂了太多的感情因素甚至谬论:
    ●对MFC的批判之一:不支持属性,MFC凭什么同其他语言抗衡?
    ●对MFC的批判之二:单调的处理方式使本来应该简单的工作变得复杂
    ●对MFC的批判之三:固步自封,不思进取
    ●对MFC的批判之四:天然的倾向性
    ●对MFC的批判之五:什么是封装?1. 不支持属性,MFC凭什么同其他语言抗衡
    首先要纠正MFC根本就不是语言,Microsoft Foundation Class,他只能算做类库级别的,不同于别的类库的是有Microsoft IDE的支持,是Microsoft的亲生儿子。另外,单单一个属性没有必要引起你这么大的不满吧?看看我写的宏:
    #define GetSetMacroForProtected(type,name) \
    protected:\
    type m_##name;\
    public:\
    type get##name() { return this->m_##name; } \
    void set##name(type name) { m_##name = name; }; 不就是几行代码的事情吗~~ 2. 单调的处理方式使本来应该简单的工作变得复杂
    这句太笼统了,所有的都单调吗?应该改成“单调的使用MFC来做优美的界面会使本来简单的工作变得复杂”会恰当些。
    MFC做界面的确不如其他的快,但是也有它的优点-可控性。这个不多说。如果你能够满足于VB、Delphi提供的千篇一律的控件,那么也没有可比性。如果想做漂亮的界面就用专门的界面开发库好了,这不能怪MFC,因为他的名字是:Microsoft Foundation Class3. 固步自封,不思进取
    MFC有生也比有死,这是任何一个产品任何一个人都无法逃脱的命运。MFC的进步落后在于微软的战略,C#的战略意义大于C++,这个是另外一个问题,原因并不在于MFC本身。下面的我就不评了~ 突然感觉花了这么多时间写这些没什么意义~~ 大家看过拉倒~~ 呵呵
      

  13.   

    但事实是,MFC的体系从MFC2.0以来就没有变动过
    ========================================我觉得可能是这个样子MS宁愿不升级一个产品,也不会去弄一个升级了却跟原来的不兼容的产品。可能MFC的基础构架决定了如果想加入现代功能,新版本就必须与之前的版本不兼容。所以,MS就不再升级MFC。而是等合适的市场时机再退出新的产品。而其他产品就不同了,比如jdom真他妈的烂啊,高版本居然把低版本的函数删去了。莫非java系统中的产品都因为被带上了跨平台的高帽而骄傲的喜欢版本不兼容?java的东西倒是能跨其他平台了,但是却跨不了自己的版本。java的东西先进型保持了,却失去了兼容性。相反,MFC的兼容性保持了,牺牲的是先进型。
      

  14.   

    MFC的CString很好用,其它的东西很少用,做界面不如Delphi快,但是可以很灵活。
      

  15.   

    对MFC的批判之一:不支持属性,MFC凭什么同其他语言抗衡?MFC什么时候成了语言了??????
      

  16.   

    对MFC的批判之一:不支持属性,MFC凭什么同其他语言抗衡?
    ========================
    由于可以看出楼主真是VC菜鸟!
    MFC里的控件都是windows标准控件,你可以调用API或成员函数去更改它的属性,难道非要像VB那样把一大堆属性都用表格的形式列出给你?如果你确实这样弱智那不能怪MFC了.
    另外,你说MFC不支持属性还真是无知,用ATL等库开发出来的控件被引入到MFC环境中,MFC难道没在属性页里列出此控件的全部属性给你吗!!
    由此可见你没深入地用过MFC,更没深入开发过COM组件!
      

  17.   

    NFC是基于windows平台的C++类库,而不是语言!楼主别太菜了在这里闹笑话!
      

  18.   

    MFC在我看来也是一堆垃圾,根本不是C++的理念来开发,微软也不是很重视这种理念,跟stl库没法比。
      

  19.   

    不知所谓。觉得好就用,不好就别用,牛了自己拿二进值自己敲个框架和界面出来,干吗在这里抨击工具呢。微软强制你用mfc了吗?
      

  20.   

    个人觉得
    ●对MFC的批判之三:固步自封,不思进取
    这一个是商业原因。
      

  21.   

    那 LZ 用 VB 好了,VB 作界面方便多了。有人认为封装的越深越好,有人则不喜欢封装。MFC 封装的恰到好处
      

  22.   

    楼主是有感情色彩,不过某些人的评论一样有感情色彩嗯是的,DELPHI的VCL库是有BUG,MFC就没BUG? DELPHI的BUG很多是开发环境的BUG,而非VCL库的BUG,各位不要用DELPHI和MFC这个库做比较,应该拿VCL和MFC做比较.
    MFC是比较灵活,有汇编灵活吗? VCL就没有MFC灵活? 各位用过多久的VCL? 有MFC能做的东西VCL做不出来的吗? 当然,这里要承认,MFC是比VCL繁琐,但是效率确实要高那么一点点.
    BCB就有属性,因为VCL库支持属性,VC为啥没有属性,因为MFC不支持属性,这个和语言是否支持属性无关,难道BCB用的不是C++?它为什么就能支持属性? 不要拿ATL来为MFC辩论,这是2个不同的东西,现在讨论的是MFC,而非ATL.反正2个库都各有千秋,都有他们存在的理由,这些东西有什么比的必要吗?
      

  23.   

    楼主说得有点过分了.我学的不是很精通,但是觉得MFC的功能是比其他的强大一些.比如自绘控件或消息传递方面..
      

  24.   

    MFC是垃圾,office也是垃圾...咋那么多人用垃圾呢..?
      

  25.   

    MFC的产生有它的历史背景,脱离了这个背景去谈问题,没实际意义,它是MVC的C / S 实现, 以前WINDOWS下的编程,都得用SDK,代码庞杂, MFC的出现,是有革命性意义的,简化了WINDOWS编程。
      

  26.   

    jiangsheng老大何必责之以苛,搂住不小心犯了个错误,只是没有注意到而已。
    总体来说,觉得搂住写的非常好即使作为VC、MFC的死忠,我也是非常乐意看到这样的文章
    这些文章带给我们对VC更多的思考,
    文中一些观点说得也非常理性。