Slashdot Mirror


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."

9 of 69 comments (clear)

  1. Meyer's books on C++ by Henry+V+.009 · · Score: 3, Interesting

    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.

  2. Best quote from the extended interview by Lumpish+Scholar · · Score: 3, Interesting

    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
  3. public final static variables in interfaces (was R by fingal · · Score: 3, Interesting
    Does anyone know why interfaces have data members at all?

    It can be a very useful way of exposing constants. For example, consider the following:-

    public interface VariableList {
    public final static String VAL1 = "val1";
    public final static String VAL2 = "val2";
    public final static String[] VAL_ARRAY = { VAL1, VAL2 };
    public final static List VAL_LIST = Collections.unmodifiableList( Arrays.asList( VAL_ARRAY ) );
    }

    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:-

    public interface CountMe {
    public Set INSTANCES = new Set();
    }

    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:-

    import java.util.*;

    public class Test {

    public Test() {
    Class1 class1 = new Class1();
    Class2 class2 = new Class2();
    Iterator instances = class1.INSTANCES.iterator();
    while( instances.hasNext() ) {
    System.out.println(instances.next());
    }
    }

    public interface CountMe {
    public Set INSTANCES = new HashSet();
    }

    public class Class1 implements CountMe {
    public Class1() {
    INSTANCES.add(this);
    }
    }

    public class Class2 implements CountMe {
    public Class2() {
    INSTANCES.add(this);
    }
    }

    public static void main(String[] args) {
    new Test();
    }
    }

    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

  4. Re:Good articles by fingal · · Score: 5, Interesting
    I actually think of this as an indicator of Bad design. Use of symbolic constants, especially as a replacement for Enum, is a serious breach of OO design in most cases. Static immutable instances of classes that the enum represents are quite often a better way to go.

    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:-

    public class MyEnum {
    private MyEnum() { }
    public final static MyEnum OPTION1 = new MyEnum();
    public final static MyEnum OPTION2 = new MyEnum();
    public final static MyEnum OPTION3 = new MyEnum();
    }

    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

  5. I've always thought Meyers was wrong about MI... by swillden · · Score: 5, Interesting

    ... 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.
  6. Re:I've always thought Meyers was wrong about MI.. by swillden · · Score: 3, Informative

    Like you, Gosling found inspiration for Java's interface from the corresponding construct in Objective-C.

    That is very cool...

    In case anyone is wondering, the Objective-C construct in question is the "protocol". A protocol is essentially nothing more than a list of methods, with no implementations. A class can indicate that it intends to "conform" to one or more protocols, and the compiler will issue a warning if doesn't implement everything. Methods can also specify that their parameters should conform to a certain set of protocols and object references (id's) can specify that they can only point to objects that conform to a certain set of protocols.

    The compiler will perform compile-time type checking wherever it has enough information. So, if you create an object instance and then a few lines later try to assign it to an id or pass it to a method that have a protocol specification, and the object doesn't implement all of the methods required, the compiler will complain. I don't think it's even necessary that the class *specify* conformance to a protocol, the compiler can still check by seeing if all of the required methods are present. Of course, if the compiler doesn't have all of the information it needs, then run-time typechecks are generated.

    Protocols were primarily invented, I believe, to make it feasible to detect errors at compile time rather than at run time. In practice, though, anyone who used them quickly discovered that they're also a very effective tool for understanding and defining the structure of a complex program -- and they did it without limiting or constraining the dynamic typing of the language at all.

    It's a small step from seeing how protocols can layer structure onto a dynamically-typed language to seeing how they can define structure in a statically-typed language, where the structure must be completely verifiable at compile time because there are limited (or no!) facilities for run-time checks.

    My favorite programming language is, and maybe always will be, Objective-C++. It turns out that although Objective-C and C++ are both OO extensions to C, they take completely different approaches, both philosophically and syntactically. In fact, the syntaxes of the extensions are so completely orthogonal that you can just lump them together into a single language, without ambiguity. Since NeXT built their Objective-C compiler on top of gcc, and others were building C++ on top of gcc, the merger was natural.

    The result is a language that has all the expressive power and flexibility of a fully dynamically-typed language *and* all of the on-the-metal performance of a statically-typed language designed to be as efficient as C. The programmer gets to choose the tradeoffs between expressiveness and performance on a class by class basis, and can easily mix and match, passing C++ objects to Objective-C class methods and vice-versa.

    Of course, the result also has all of the arcane complexity of C++, and although Objective-C is very simple, the resulting design decisions are anything but, since there are two very different views of object orientation to be mixed and matched. For the programmer who has mastered both views and also understands the dusty corners of C++, the combination is extremely powerful and, IMO, wholly appropriate to everything from on-the-metal bit twiddling to rapid development of large, complex applications...

    ... as long as they can be written by this single programmer, because the odds of finding two people who can agree on enough of the myriad design tradeoffs to get any useful work done is next to nil. And don't even *think* about bringing a novice developer onto the project.

    --
    Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
  7. Re:Scott Meyers by elflord · · Score: 3, Funny
    If he'd stayed in college and got his degree, maybe he could write with some authority, but as it stands... No.

    He has a Ph.D. Have a nice day.

  8. C++ community not using interfaces? by spongman · · Score: 4, Interesting
    But I would say that while the C++ community was focusing on templates, the STL, and exceptions... what they were not doing was component-based development.
    I don't know where Scott's been for the last 10 years but COM specifically uses multiple inheritance of abstract base classes without data or implementation to specify interfaces for component-based development (and I believe that CORBA does the same).

    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?

  9. Re:Good articles by Anonymous+Brave+Guy · · Score: 3, Insightful
    Does anyone know why interfaces have data members at all?

    They wouldn't normally have state, but there might be constants relating to the interface itself, typically passed used when determining what parameters to pass to functions in that interface. Given Java's lack of enumerated types, this is particularly important to avoid passing magic numbers or arbitrary boolean parameters everywhere.

    --
    If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.