C++ – What’s the fundamental difference between MFC and 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:

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?

Best Solution

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.