Scott Meyers on Programming C++
Bill Venners writes "Artima.com has published a four-part interview with Scott Meyers, author of Effective C++, More Effective C++, and Effective STL. In Multiple Inheritance and Interfaces, Scott describes how his view of multiple inheritance has changed with time, the C++ community's take on Java's interface, and a schism of focus between the C++ and other prominent development communities. In Designing Contracts and Interfaces, Scott discusses interface contracts, private data, and designing minimal and complete interfaces. In Meaningful Programming, Scott discusses the importance of saying what you mean and understanding what you say, the three fundamental relationships between classes, and the difference between virtual and non-virtual functions. In Const, RTTI, and Efficiency, Scott describes the utility of const, the appropriate time to use RTTI, a good attitude about efficiency, and Scott Meyers' current quest for general programming principles."
I own each of Meyer's books, and they are all wonderful. If you work with C++ in any sort of professional capacity get a hold of copies right now.
Meyers: "... we have templates in C++, but there's no way to write user interfaces or talk to databases. Java has no templates, but you can write user interfaces up the wazoo and you can talk to databases with no trouble at all."
Stupid job ads, weird spam, occasional insight at
It can be a very useful way of exposing constants. For example, consider the following:-
This will provide you with a slightly more flexible set of constants that are automatically acquired by anything that implemnts the VariableList interface.
Alternatively, you can use Mutable variables. Remember that it is only the references to the variable that is final. If the Object itself contains information then it accessed by all classes that implement the interface. For example:-
If we now stipulate that all instances of CountMe that want to be included in the CountMe functionality should register themselves inside the INSTANCES variable, for example:-
and there you have it - data sharing across interfaces with no extending classes at all. Of course, you cannot force classes to register themselves in the INSTANCES variable, but if you wanted to extend a couple of base classes then it would be trivial to make a couple of implementations of CountMe that extend each of them which enforce the functionality explicitly.
The only Good System is a Sound System
The Static immutable instances of classes gets half-way there, but doesn't stop people creating new instances of the classes and then you are back where you where to begin with. A better thing to do is to forcibly limit the instances of the classes to a fixed number of instances like so:-
Now you are guaranteed that there is only ever going to be MyEnum.OPTION1, MyEnum.OPTION2 and MyEnum.OPTION3.
The only Good System is a Sound System
From C++ Answers From Bjarne Stroustrup:
I think my most obvious mistake was not to introduce templates before multiple inheritance and not to ship a larger library with Release 1 of my C++ compiler
Does he still favor a minimal library? If so, does anyone know why?
... and this article has helped me to understand precisely why we disagreed. And he's still wrong, although he's getting closer.
I've been writing C++ code professionally since about 91, when Scott published his first book. I think I was lucky that I didn't come across his book for a few years, particularly because of his skepticism of MI. I might have followed his advice and my career would have been the worse for it.
I have always made heavy use of MI in my code, and 80% of the time I've written C++ classes that are exactly analogous to Java interfaces; it just always seemed like a good idea to me. Also, I was a big fan of Robert C. Martin and his notions about how you can analyze design quality by looking at the abstractness of the classes and the dependencies between them (dependencies on abstract classes, especially pure abstract classes(*) are, much better than dependencies on classes that do a lot of stuff for the simple reason that classes that do a lot have more potential to change, so purely abstract firewalls tend to limit the ripple effect).
To avoid self-aggrandizement, I didn't independently invent the notion of pure abstractions. I had fiddled with Objective-C and it had a construct (whose name I forget) that allowed you to define a pure interface. You could then use that pure interface type as a function parameter and the compiler would verify that objects you passed to that function met the interface requirements -- allowing you to get compile-time typechecking in an otherwise completely dynamically-typed language.
However, as I said, I think only about 80% of my MI usage is with pure abstractions. Probably 10% of the time I use MI, I do it to facilitate a style of programming called "mix-in" programming. The idea is that you have a bunch of purely abstract classes that define the potential interfaces, and you have a bunch of concrete classes that implement the pure abstractions in various useful ways and then you can create useful classes by mixing together appropriate base classes (with the occasional bit of glue). Mix-ins aren't appropriate for everything, but they can be a very elegant solution for many toolkit kinds of scenarios. Diamond inheritance doesn't really happen, because none of the mixed-together classes have enough code in them to make it worth inheriting from them. If you need something almost like one mixed-together class, you just mix a completely new one.
In practice, not only do pure abstractions and mix-ins sidestep all of the "problems" that make people leery of MI, they're also not at all confusing to less competent programmers. I've found that with just the tiniest explanation of how the structure is put together, people can see immediately how it works and why it's good (well, once they've understood the idea of polymorphism, anyway).
I think C++ MI can also be used more fully to good effect, but that must, indeed, be done judiciously.
(*) Scott said in the interview that the C++ community doesn't have a name for interface classes. Maybe not, but I've been using the term "pure abstract class" for close to a decade and I don't think I've come across a single marginally-competent C++ programmer who didn't immediately understand the term, and I'm pretty sure I picked the term up from comp.lang.c++.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
I'd guess that win32 C++ programmers make up the largest such subset of all C++ programmers. So which C++ community is he talking about exactly?
I can list off 10,000 reasons why C shouldn't be used for much of anything. I have a masters in software engineering from SEI and I can list off dozens of real world fuckups that were caused or allowed because of the C language and costed millions of dollars and at times possibly even risked lives. Then you go out into the world and you will continually stumble into situation when you want portable assembly and there is no better than C. Would I write the code that controls the 767 in C? Not if I didn't have to. Would I write a huge GUI with hundreds of dialogs and controls in C? Not unless you were holding a weapon and threatening me. Now a kernel? A low level library? Something that talks to the metal? I don't know of anything better than C. Ada is nice at times, Forth is wonderful for certain tasks. C is amazing at most of it. You can see the opcodes that get produced as you write it, it's beautiful. Last embedded project I built from scratch we wrote enough assembly to get a CRT0 working and then enough C to get a JVM working and the rest was gravy.
I can wax the same way about gotos. I can point to pieces of code that a absolutely beautiful because they have gotos and couldn't be made as elegent without them. Drivers in the linux kernel use them from time to time. Mind you, most of this stuff is low level but that's what it's for. Tool for the job, you know? And it's beautiful when it works.
In the hands on a newbie it is a little frightening. I think of it like the table saw in shop class. It's the most deadly tool in the room, every shop teacher has personal stories to tell you about kids sawing fingers off and stuff. And without exception there will come a time when that's the tool that does the best job. Sure you could rip a 2x4 in to a 2x2 with a ban saw or even a jig saw but the table saw is the saw intended for that task and it will do it in seconds, perfectly. OOP exists because we think it's easier to model programs in the ways that we think, rather than the ways that computers need them; there is nothing you can build with OOP that you couldn't build with functional or imparitive programming only you might find it easier to do with OOP. So what happens when I can describe something with 2 concrete abstractions? You're saying I should use an abstract abstraction as an inermediate? Take a book, it is a phyiscal collection of bound and printed pages, it is also the collection of words on those pages and in programming land those are both concrete (the specific words are what make the book.) So what if I had a "CollectionOfOrderedWords" object and a "CollectionOfBoundPages" object, my book could be a child of both, specifically myBook might be the mapping between the words and the specific pages. As such I also want to treat it as both. The interface world requires that I actually treat it differently because I want to look at the words rather than the pages. What if I think that abstraction is easier to think about?
MI has it's problems. It's not the safest thing to use but it makes some things very easy. Particularly when you're building complex things rather than decomposing complex things, which seems to be the tendency among a lot of OOP programmers. If you're building a "final" object that won't be a component of anything else, MI is awesome.