MFC和ATL之间的根本区别是什么?

2022-01-12 00:00:00 visual-c++ c++ mfc atl

假设我仅将它们用于普通"GUI 程序(没有 COM,没有 ActiveX,没有什么花哨的),我将看到 ATL 和 MFC 之间的根本区别是什么?帮我弄清楚该用哪一个?

<小时>

我在网上做了一些搜索,但最终没有一个答案真正回答了我的问题:

  • http://msdn.microsoft.com/en-us/library/bk8ytxz5(v=vs.80).aspx:

    • ATL 是一种快速、简单的方法,既可以在 C++ 中创建 COM 组件,又可以保持较小的占用空间.如果您不需要所有内置功能,请使用 ATL 创建控件MFC 自动提供的."

      并没有真正回答我的问题,因为:

      • 我没有使用 COM.

      • 这是否意味着 MFC 不快?为什么/如何?

    • MFC 允许您创建完整的应用程序、ActiveX 控件和活动文档.如果您已经使用 MFC 创建了控件,您可能希望在 MFC 中继续开发.创建新控件时,如果您不需要 MFC 的所有内置功能,请考虑使用 ATL."

      也没有回答我的问题,因为:

      • 一开始我什至不知道 ActiveX 是什么.

      • 微软似乎不鼓励使用 MFC,但我不知道为什么.

      • 究竟是什么是 ATL 不提供的 MFC 的内置功能"?

    • 总的来说,这并不能回答我的问题,因为它没有解释缺点及其背后的原因.

因为直接或间接地,一切似乎都链接回了上一页:

  • 我如何决定是否为新的 C++ 项目使用 ATL、MFC、Win32 或 CLR?

    • 在 ATL 和 MFC 之间做出选择有点棘手. [[别开玩笑!]] 我建议你参考 MSDN 的页面 供选择以便在它们之间做出决定."p>

      显然,这并没有回答我的问题.:)

  • http://www.codeguru.com/forum/archive/index.php/t-64778.html

我目前观察到的(在过去几天内,同时尝试学习两者):

  • ATL 基于模板或编译时多态性.
    • ATL 方法往往是非虚拟的,并且往往会返回引用.
  • MFC 基于虚拟方法或运行时多态性.
    • MFC 方法往往是虚拟的,并且往往返回指针.

但是它们之间似乎没有任何架构差异:

  • 两者都使用消息映射(BEGIN_MSG_MAPBEGIN_MESSAGE_MAP... 很重要)
  • 两者都将 Win32 方法包装到类中
  • 两者似乎都有相似的类 CWndCWindow

但是,如果除了编译时和运行时方面没有真正的区别,那么为什么它们都存在呢?一个还不够吗?

我在这里错过了什么?

解决方案

如果你回顾一下这两个库是如何起源和演变的,我认为你的问题的答案主要是历史性的.

简短的回答是,如果您没有做任何花哨"的事情,请使用 ATL.它非常适合带有 COM 的简单用户界面.

长答案:MFC 是在 90 年代初构建的,旨在尝试这种称为 C++ 的新语言并将其应用于 Windows.当操作系统还没有类似 Office 的功能时,它使开发社区可以使用这些功能.

当时这个库非常原始,因为 C++ 语言和编译器都是新的,而且微软随着 Office 的发展逐渐构建它.

由于这段历史,MFC:

  1. 有一个相当笨重的设计.它最初是作为 Windows API 的轻量级包装器,但后来发展壮大.由于编译器和语言不支持它们,因此必须发明许多小功能".没有模板,他们发明了一个字符串类,他们发明了列表类,他们设计了自己的运行时类型标识,等等.
  2. 封装了 Office 和 Windows 20 年的发展历程,其中包括一大堆您可能永远不会使用的东西:单文档和多文档界面、DDE、COM、COM+、DCOM、文档链接和嵌入(因此您可以嵌入如果您愿意,可以在您的应用程序中使用 word 文档)、ActiveX 控件(Web 对象嵌入的演变!)、结构化文档存储、序列化和版本控制、自动化(从早期的 VBA 开始),当然还有 MVC.最新版本支持 Visual Studio 样式窗口停靠和 Office 功能区.基本上,20 年来雷德蒙德的每一项技术都在某个地方.这只是巨大的!
  3. 有大量的小问题、错误、变通方法、假设、支持仍然存在但您永远不会使用的东西,它们会导致问题.您需要非常熟悉许多类的实现以及它们如何交互才能在一个体面的项目中使用它.在调试期间深入研究 MFC 源代码是很常见的.找到一个 15 年前的技术说明关于某些指针为空导致崩溃仍然发生.对古代文档嵌入内容初始化的假设可能会以奇怪的方式影响您的应用程序.MFC 中没有抽象之类的东西,你需要每天处理它的怪癖和内部结构,它不会隐藏任何东西.不要让我开始使用班级向导.

ATL 是随着 C++ 语言的发展和模板的出现而发明的.ATL 展示了如何使用模板来避免 MFC 库的运行时问题:

  1. 消息映射:因为它们是基于模板的,所以会检查类型,如果你搞砸了绑定函数,它就不会构建.在 MFC 中,消息映射是基于宏的,并且是运行时绑定的.这可能会导致奇怪的错误、消息路由到错误的窗口、如果您的函数或宏定义不正确会导致崩溃,或者只是因为某些东西没有正确连接而无法正常工作.更难调试,更容易在不注意的情况下破解.
  2. COM/自动化:与消息映射类似,COM 最初是使用宏在运行时绑定的,需要大量错误处理并导致奇怪的问题.ATL 使其基于模板、编译时间受限并且更容易处理.

这些小改进使 ATL 在不需要 MFC 的所有 Office 功能的简单应用程序上更容易处理.带有简单 UI 和一些 Office 自动化的东西.它体积小、速度快、编译时间受限,为您节省了很多时间和头痛.MFC 有一个庞大的类库,这些类可能很笨重且难以使用.

不幸的是,ATL 停滞不前.它有用于 Windows API 和 COM 支持的包装器,然后它从未真正超越这一点.当网络起飞时,所有这些东西都作为旧新闻被遗忘了.

MFC 的巨大足迹让他们无法倾倒,所以它仍然发展缓慢.模板以及其他语言和 API 增强功能已重新合并到库中.(直到看到这个问题,我才听说过 WTL.:)

最终,使用哪一个只是偏好问题.您需要的大部分功能都在基本 OS API 中,如果库中没有合适的包装器,您可以直接从任一库中调用它.

多年使用 MFC 只需我的 2 美分,现在我每天都在使用它.当 ATL 在几个项目中首次发布时,我涉足了几年.在那些日子里,这是一股新鲜空气,但从未真正去任何地方.然后网络出现了,我忘记了一切.

<小时>

这个答案具有惊人的寿命.由于它不断在我的堆栈溢出页面中弹出,我想我会在我认为缺少的原始答案中添加一些修饰.

Assuming I am only using them for "normal" GUI programs (no COM, no ActiveX, nothing fancy), what is the fundamental difference I will see between ATL and MFC, to help me figure out which one to use?


I've done some searches on the web, but ultimately none of the answers really answered my question:

  • http://msdn.microsoft.com/en-us/library/bk8ytxz5(v=vs.80).aspx:

    • "ATL is a fast, easy way to both create a COM component in C++ and maintain a small footprint. Use ATL to create a control if you don't need all of the built-in functionality that MFC automatically provides."

      Doesn't really answer my question, because:

      • I'm not working with COM.

      • Does this imply MFC isn't fast? Why/how?

    • "MFC allows you to create full applications, ActiveX controls, and active documents. If you have already created a control with MFC, you may want to continue development in MFC. When creating a new control, consider using ATL if you don't need all of MFC's built-in functionality."

      Also doesn't answer my question, because:

      • I don't really even know what ActiveX is in the first place.

      • It looks as though Microsoft is discouraging the use of MFC, but I can't figure out why.

      • What exactly is MFC's "built-in functionality" that ATL doesn't provide?

    • In general, this doesn't answer my question because it doesn't explain the downsides and the reasons behind them.

because directly or indirectly, everything seems to link back to the previous page:

  • How do I decide whether to use ATL, MFC, Win32 or CLR for a new C++ project?

    • "ATL & MFC are somewhat trickier to decide between. [[No kidding!]] I'd refer you to MSDN's page for choosing in order to decide between them."

      Obviously, this doesn't answer my question. :)

  • http://www.codeguru.com/forum/archive/index.php/t-64778.html

  • etc.

What I have currently observed (within the last couple of days, while trying to learn both):

  • ATL is based on templates, or compile-time polymorphism.
    • ATL methods tend to be non-virtual, and tend to return references.
  • MFC is based on virtual methods, or run-time polymorphism.
    • MFC methods tend to be virtual, and tend to return pointers.

But there doesn't seem to be any architectural difference between them:

  • Both use message maps (BEGIN_MSG_MAP vs. BEGIN_MESSAGE_MAP... big deal)
  • Both wrap Win32 methods into classes
  • Both seem to have similar classes CWnd vs. CWindow

But then, if there's no real difference except for the compile-time vs. run-time aspect, then why do both of them exist? Shouldn't one of them be enough?

What am I missing here?

解决方案

I think the answer to your question is mostly historical, if you look back at how the two libraries originated and evolved through time.

The short answer is, if you are not doing anything "fancy", use ATL. It's great for simple user interfaces with COM thrown in.

The long answer: MFC was built in the early 90s to try out this new language called C++ and apply it to Windows. It made Office like features available to the development community when the OS didn't have them yet.

[Edit embellishment: I did not work at Microsoft, so I don't know if Office was ever built on MFC, but I think the answer is no. Back in Win 3.1, Win 95 days, Office UI team would invent new controls, package them up in libraries, then the Windows and MFC teams would incorporate wrappers and API to those controls with redistributable dlls. I would guess there was a bit of collaboration and code sharing between those teams. Eventually those controls would make it into the base operating system in service packs or the next Windows version. This pattern continued with the Office Ribbon which was added into Windows as an add-on component well after Office shipped, and is now part of the Windows OS.]

At that time the library was quite primitive, both because of the C++ language and compiler being new, and Microsoft building it up over time as Office evolved.

Because of this history, MFC:

  1. Has a fairly clunky design. It started as a light wrapper around the Windows API, but grew. There are a bunch of little 'features' that had to be invented because the compiler and language just didn't support them. There were no templates, they invented a string class, they invented list classes, they designed their own run time type identification, etc.
  2. Encapsulates 20 years of Office and Windows evolution, which includes a whole crap load of stuff you will probably never use: Single and Multiple Document interfaces, DDE, COM, COM+, DCOM, Document Linking and Embedding (so you can embed a word document in your app if you wanted to), ActiveX controls (evolution of object embedding for the web!), Structured Document Storage, Serialization and Versioning, Automation (from early VBA years), and of course MVC. The latest versions have support for Visual Studio style window docking, and the Office ribbon. Basically every technology out of Redmond in 20 years is in there somewhere. It's just HUGE!
  3. Has a ton of little gotchas, bugs, workarounds, assumptions, support for things that are still there that you will never use, and they cause problems. You need to be intimately familiar with the implementation of many classes and how they interact to use it on a decent size project. Delving into MFC source code during debugging is common. Finding a 15 year old tech note on some pointer being null causing a crash still happens. Assumptions on initialization of ancient document embedding stuff can affect your application in weird ways. There's no such thing as abstraction in MFC, you need to work with it's quirks and internals daily, it doesn't hide anything. And don't get me started on the class wizard.

ATL was invented as the C++ language evolved, and templates arrived. ATL was a showcase of how to use templates to avoid the run-time problems of the MFC library:

  1. Message maps: Since they are template based, types are checked, and if you screw up the bound function, it doesn't build. In MFC message maps are macro based, and run-time bound. This can cause odd bugs, message routed to the wrong window, a crash if you have function or macro defined incorrectly, or just simply not work because something isn't hooked up right. Much more difficult to debug, and easier to break without noticing.
  2. COM/Automation: Similar to message maps, COM was originally run-time bound using Macros, requiring lots of error handing and causing odd problems. ATL made it template based, compile time bound, and much, much easier to deal with.

[Edit Embellishment: At the time ATL was created, Microsoft's technical road map was mainly focused on 'Document Management'. Apple was killing them in the desktop publishing business. Office 'Document Linking and Embedding' was a main component to enhancing the 'Document Management' features of Office to compete in this space. COM was a core technology invented for application integration, and Document Embedding API's were based on COM. MFC was difficult to use for this use case. ATL was a good solution to make this particular technology easier for 3rd party's to implement COM and utilize document embedding features.]

These little improvements make ATL hugely easier to deal with on a simple application that doesn't need all the office like features of MFC. Something with a simple UI and some Office automation thrown in. It's small, it's fast, it's compile time bound saving you much time and headache. MFC has a huge library of classes that can be clunky, and difficult to work with.

Unfortunately ATL stagnated. It had wrappers for the windows API and COM support, and then it never really went beyond that. When the Web took off, all this stuff was sort of forgotten as old news.

[Edit Embellishment: Microsoft realized that this 'Internet Thing' was going to be big. Their technical road map changed drastically to focus on Internet Explorer, Windows Server, IIS, ASP, SQL Server, COM/DCOM in Distributed Transaction Server. So the Document Linking and Embedding was no longer a high priority.]

The huge footprint of MFC made it impossible for them to dump, so it still evolves slowly. Templates have been incorporated back into the library, as well as other language and API enhancements. (I had not heard of WTL until I saw this question. :)

Ultimately, which one to use is simply a matter of preference. The majority of the features you need are in the base OS API, which you can call directly from either library, if there is no suitable wrapper in the library.

Just my 2 cents based on using MFC for many years, and I use it now daily. I dabbled in ATL when it was first released on a few projects for a couple of years. It was a breath of fresh air in those days, but never really went anywhere. And then the Web came along and I forgot all about it.


Edit: This answer has surprising longevity. Since it keeps popping up in my stack overflow page, I thought I'd add some embellishment to the original answer I thought was lacking.

相关文章