First let me say that my experience with MFC is limited. Most of my systems use commercial or proprietary RTOSes. So my insight into MFC is far from definitive. STL on the other hand I have significant practical experience with and David Musser (one of the founding authors of STL) was a professor of mine during my undergraduate work at RPI. Yes, you would think that this would unfairly bias me towards STL but the opposite is true. Early versions of STL (including those that morphed into the HP version) were horrendous to use. I spent many years since avoiding STL where possible. It has been a hard road back to recognize STL’s true genius.
But from my limited view I don't think your analysis of MFC as...
is that far off. It does seem as though its primary purpose is to provide an OO interface to the WIN32 API. This is of course very useful. How many times have we looked on in disgust at a beautifully crafted object that is forced to embed an OS C system call (ala POSIX or WIN32)?Quote:
... MFC is a GUI library that wraps the Win32 API and adds some extensions like DOC/VIEW.
STL on the other hand was intended to provide a library of ‘generic’ containers and efficient algorithms for operating on containers. In STL the term ‘generic’ does not simply mean reusable but relying on only the most basic of semantic relationships as forwarded by the ‘generic programming’ sub-discipline. In STL the generic philosophy can be seen manifest in the relationship between containers, interators and algorithms. Iterators provide the access and operations for containers as required by algorithms so allowing algorithms to interoperate with any number of differing types of containers. Since a container need only provide the correct iterator to be useable by an algorithm – no inheritance (IS-A, refinement) relationship need exist between containers. This in turn allows each container’s interface to be unique to its intent and capability and eliminates performance and design coupling associated with virtual functions. The tradeoff is that the type of the container (or actually the iterator’s type) must be determinable at compilation time.
If types truly cannot be ‘known’ at compilation time then inheritance is required though it is often useful even when the types are known to control the code-bloat associated with templates which would have to be instantiated on a large number of types.
Everyone knows that you can use STL containers on polymorphic data but since you cannot inherit (safely) from STL types, people assume that you cannot have run-time polymorphic STL objects (ie. Run-time determination of what container type you are passing into an algorithm). This can easily be achieved though a customer iterator type that contains a polymorphic member. In this way, the exterior iterator type (your custom iterator) passed to the algorithm is static, yet the iterator forwards operations to a polymorphic member whose type is run-time dependent.
I know, I know. Its just hard in a busy schedule to find the time to whip up meaningful example code for a discussion forum. The polymorphic member approach is heavily used in policy-based libraries like LOKI from A. Alexandrescu's "Modern C++ Design: Generic Programming and Design Patterns Applied" (a most mis-titled book) but not for STL. If someone is very VERY intrested I will put together the code for polymorphic iterators.Quote:
Again, how about some details. I am not trying to be rude, it is just that it would be nice to learn something.
A virtual function call is always more expensive than a normal function call unless the compiler can determine the type – but since we are assuming that inheritance was dictated by at least one instance where the type is ‘unknowable’ it is fair to say that overall it is more expensive. But it is the only way. If you really need run-time polymorphism (either because types are unknowable or instantiation of templates on all required types is to great) then you must pay for it. Nothing including polymorphism is free.
The real difference on the inheritance vs. templates in MFC and STL is that STL does not require you to pay for something unless you use it. If you want run-time polymorphism of STL objects (not just STL objects containing polymorphic data) then you have to pay for it using run-time polymorphic members within your own iterator type.
As far as the single-rooted hierarchy style of MFC – there are a number of papers/books critiquing this design style. Given MFC’s focus on GUI construction, the single-rooted approach is of no surprise since there is a strong history of single-rooted hierarchies in OO GUI tool-kits.
We are in violent agreement.Quote:
A vector is a vector. The usual reason to want to inherit from it is, for example, to have a vector that does this or that. I believe the proper way to think is that I have a vector that I perform this or that on, not a vector that does this or that.
