Sponsored Link •
Scott Meyers, C++ expert and author of numerous books including Effective C++, talks with Bill Venners about multiple inheritance and
Scott Meyers is one of the world's foremost experts on C++ software development. He wrote the best-selling Effective C++ series (Effective C++, More Effective C++, and Effective STL), wrote and designed the Effective C++ CD, is consulting editor for Addison Wesley's Effective Software Development Series, and is a member of the advisory board for Software Development magazine. A programmer since 1972, he holds an M.S. in Computer Science from Stanford University and a Ph.D. from Brown University.
In this four-part interview, which will be published in weekly installments, Meyers gives
his views on many topics of object-oriented design, including the use of multiple
inheritance in light of Java's
interface, designing minimal and complete
interfaces, public data members and contracts, and the utility of
this initial installment, Meyers indicates how his view of multiple inheritance has
changed with time, describes the C++ community's take on Java's
interface, and points out a schism of focus between the C++ and other
prominent development communities.
Bill Venners: Your book Effective C++ was the first book
on object-oriented programming that I bought, and I picked up a lot of fundamentals from
it. For example, I had never heard of ISA (as in an
ArrayList IS A
List) before reading your book. Your guideline, "Make sure
public inheritance models ISA" was my first introduction to that idea. I probably hadn't
even heard that data should be private before reading your book.
I read Effective C++ back in the early 90s, when I was moving from C to
C++. Much of my philosophy of object-oriented design originally came from your book,
but since then I've changed the way I think about design in some ways. I'm curious how
your ideas of object-oriented design may have changed or evolved since you wrote
Effective C++. My first question for you involves multiple inheritance and
Any time you used the word "judiciously" in an Effective C++ guideline it really scared me away. For example, you said, "Use private inheritance judiciously." I didn't just use private inheritance judiciously, I never used it at all. You said, "Use multiple inheritance judiciously." In five years of C++ programming, I never once used multiple inheritance.
My attitude about multiple inheritance in C++ didn't come only from your book. Most of my friends who were programming in C++ shared that attitude. The way we thought about multiple inheritance was that given two full blown classes, each of which could be instantiated, you create a third full blown class that inherits from the other two. That class structure, which is what we thought of when we thought of multiple inheritance, has all the problems you describe in Effective C++. I wasn't determined to avoid multiple inheritance in C++ at all costs, but in five years I never encountered a situation in which I felt inheriting from multiple base classes made sense in my designs.
When I moved from C++ to Java in early 1996, however, I encountered Java's
interface. I quickly learned the mechanics of Java's
interface—I understood how it worked—but
I didn't know how to design with it. Here was multiple inheritance
again, but not the full blown kind of multiple inheritance I was used to in C++. With
interface construct, I could multiply inherit interface but not
implementation. In the C++ terminology you used in Effective C++, Java
only let me multiply inherit from abstract base classes (ABCs) that had no data members
and only pure virtual functions.
Bill Venners: Why did Java only allow multiple inheritance of interface? How should I apply
interfaces in Java designs? I didn't know, but I did soon realize that
although in five years of C++ I never once used multiple inheritance, I was finding Java's
special kind of multiple inheritance very useful. The process of struggling with Java's
interface changed the way I think about object-oriented design in general.
Were I to go back to C++ now, I would make much more use of ABCs that have no data
members and only pure virtual functions.
I'm curious if you've had any similar transformation regarding multiple inheritance. Is there anything you would say about ABCs or multiple inheritance and their place in designs now that you didn't say 10 years ago?
Scott Meyers: I don't have a lot that is new, but I would say two
things. First, if you look at
interfaces in Java or .NET, in addition to being
interfaces also have no data. I have come to appreciate that if you
use abstract base classes and eliminate any data from them, then a lot of the difficulties of
multiple inheritance that I wrote about just go away, even in C++.
I happen to think one of the contributions of Java was getting rid of some of the baggage
that comes with multiple inheritance in C++. I'm guessing, since I'm not a Java guy, that
the creators of Java looked at the multiple inheritance model of C++. They said, "This has
some good things, but it has some baggage too. So we're going to try to find a way to
have the good stuff and throw away the baggage." That's essentially what an
interface is. It is an abstract base class that doesn't have any of the things
that tend to give rise to trouble in C++, because it doesn't have any data. I think that's an
interesting idea. So I think
interfaces are an interesting idea.
Second, at the time in 1991 when I wrote that multiple inheritance guideline in Effective C++, a huge debate about multiple inheritance was raging in the C++ community. My advice to use multiple inheritance judiciously was based on two observations. First, at that particular time no one had really come out with a compelling example in which multiple inheritance was useful and there was no competing design that was at least as good. Second, even some of the people who had used multiple inheritance didn't have great things to say about it. Notably, Jerry Schwartz, who had implemented the IO streams library based on multiple inheritance, had publicly said that if he had it to do over again he would not use multiple inheritance. He would find some way to get rid of the multiple inheritance.
At the time I wrote that guideline in 1991 I had never seen a compelling example for the
use of multiple inheritance. I knew about the difficulties with multiple inheritance that I
have written about. At the time I was not talking about
they didn't exist in that name. And somebody like Jerry, who had a lot of experience with
multiple inheritance, was saying if he had to do it over again he would have found a way
to get rid of the multiple inheritance. That was the reason for my advice about multiple
inheritance at that time.
A certain amount of time has gone by. My feeling about multiple inheritance now is that
as long as you go into it with your eyes open, so you understand the kinds of things I
wrote about in the book, especially if you are using
that have no data, you will be able to side-step most of those difficulties. So I'm less
down on multiple inheritance now.
Frankly, though, my advice would not change. I would still say use multiple inheritance
judiciously, because if you have a choice between a single inheritance based design and a
multiple inheritance based design, I think most of the time the single inheritance based
design will be simpler. And I like simpler better than more complicated. But perhaps you
are faced with a multiple inheritance based design and a single inheritance based design,
and the multiple inheritance based design strikes you as being cleaner or in some other
way advantageous. As long as you've taken into account the difficulties with multiple
inheritance that have been talked about, probably you've eliminated them by using
interface classes, then I would say fine, follow your design instinct and
use the multiple inheritance. So my tone on multiple inheritance has softened a little bit.
Bill Venners: If public inheritance means ISA, what does ABC inheritance mean?
Scott Meyers: ABC inheritance still means ISA. Public inheritance always means ISA. That's just what it means. If you are inheriting from an ABC, all you are saying is, "I'm going to inherit an interface, and that particular interface can never be instantiated." But in C++ there can still be data in the ABC, and there are certainly going to be virtual member functions, so you still have behavior. Publicly inheriting from an ABC just means that every instance of my class IS AN instance of this ABC. That's what the inheritance is asserting. That's what ISA means. "I am one of those." The fact that the base class is an ABC says, "By myself, I am not complete enough to be instantiated." But those are orthogonal statements.
Bill Venners: Let's define ABC. ABC means abstract base class. So what would you call in C++ that special case of an ABC that has no data and nothing but pure virtual functions, which have no implementation.
Scott Meyers: The C++ community does not have a name for that.
There is no commonly accepted term for that kind of class. Some people call it "interface
class." Some people quite incorrectly call it a virtual base class, but as long as we are
among friends and know what we are talking about, that's OK. But the notion of
essentially a C++ implementation of an
interface in Java or C# does not
have a name in C++.
Bill Venners: I found in coming to Java that
are a very useful tool in designs. Were I to go back to C++, I would use them a lot more.
That's how I would now use multiple inheritance in C++.
Interfaces you mean?
Bill Venners: Interface classes, or whatever you want to call them. I
am wondering to what extent the C++ community has discovered this usefulness that I
interfaces provide in Java. I see it as something that's generically
useful in object-oriented design. The fact that Java had a special construct called
interface forced me to figure out what to do with it in 1996. That's how I
discovered this useful tool of OO design. But if the C++ community doesn't have a
special name for it, then maybe that community really hasn't been turned on by
Scott Meyers: I think two things have happened. First, experienced designers of frameworks and libraries had already decided that that particular kind of abstract base class was particularly useful. They were using them. They just didn't have a particular name for them. Second, in the past last five or six years, almost all of the attention in the C++ community has been focused on two features of the language: exceptions and templates. Templates and the standard template library (STL) have received a huge amount of attention. As a result, the object-oriented part of the language has not received very much attention. If I had to give a reason why there doesn't seem to be a common name for interface classes in the C++ community, I would say probably the most important reason is simply because the entire language community has been focused so much more on these other features, exceptions and templates, that they did not know how to use.
I'm going to speculate now, because I haven't been watching Java and I've just got my feet a little bit wet in .NET. But I would say that while the C++ community was focusing on templates, the STL, and exceptions—oddly enough the three are wrapped up together pretty closely—what they were not doing was component-based development. For example, there is no huge collection of class libraries for C++. The standard library for C++ is pretty impoverished. In the meantime, the rest of the world was busy creating huge class libraries that let you write all kinds of really neat applications without having to write very much code. Certainly Java is famous for its libraries. .NET has a huge number of libraries.
I think a schism existed between the C++ community, which was still focused on language issues, and the other prominent development communities, which pretty much left the language alone. Java already had exceptions, but didn't have templates and had nothing like the STL. Yet the Java community focused on writing a whole bunch of libraries that everybody can assume will exist everywhere, libraries that will let you write applications really quickly. The end result is, 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.
Effective C++, Second Edition, by Scott Meyers is at Amazon.com at:
More Effective C++, by Scott Meyers is at Amazon.com at:
Effective STL, by Scott Meyers is at Amazon.com at:
Effective C++ CD, by Scott Meyers is at Amazon.com at:
Scott Meyer's website contains links to many publications, presentations, books, and other information from Scott:
Images of Persephone, the best dog in the world: