TITLE: thoughts on protected inheritance (Newsgroups: comp.lang.c++.moderated, 6 Feb 99) NARAN: Siemel Naran >>Protected inheritance is kind of like protected data -- it's neither >>here nor there. All the same, 'protected' does hold an important >>place in the C++ language. In particular, protected member functions >>along with private data don't violate encapsulation. MEYERS: Scott Meyers >Actually, they do. As I remarked in a separate post, an arbitrarily large >number of clients will be broken if anything in the public *or protected* >part of a class changes. Remember that derived classes are clients, too. > >>class Activity : protected WindowInterface, protected Calender { }; > >This is not compelling. I remain open-minded, but unconvinced. > >I find it easiest to understand how features in C++ should be used if I >first understand what they mean. In Effective C++, I argue that public >inheritance means "isa". I argue that private inheritance means "is >implemented in terms of". I argue that nobody seems to know what protected >inheritance means. I still believe that. ------------------------------------------------------------------- MEYERS: "Scott Meyers" >> I find it easiest to understand how features in C++ should be used if I >> first understand what they mean. In Effective C++, I argue that public >> inheritance means "isa". I argue that private inheritance means "is >> implemented in terms of". I argue that nobody seems to know what >> protected inheritance means. I still believe that. SUTTER: Herb Sutter >I have struggled with this for years. The best I've been able to do is >say that protected inheritance means "is implemented in terms of, plus >isa for my derived classes only." Because of that, my belief is that >"protected inheritance is necessary" implies "the class has [at least] >two distinct responsibilities" [which should be separated/factored per >sound engineering guidelines]. > >Here's a snip from my column in a recent C++ Report (Oct98): > >There is one additional feature we can get using nonpublic >inheritance, and it's the only one that doesn't model >IS-IMPLEMENTED-IN-TERMS-OF: >· We need "controlled polymorphism" - LSP IS-A, but in certain code >only. Public inheritance should always model IS-A as per the Liskov >Substitution Principle (LSP). Nonpublic inheritance can express a >restricted form of IS-A, even though most people identify IS-A with >public inheritance alone. Given class Derived : private Base, from the >point of view of outside code, a Derived object IS-NOT-A Base, and so >of course can't be used polymorphically as a Base because of the >access restrictions imposed by private inheritance. However, inside >Derived's own member functions and friends only, a Derived object can >indeed be used polymorphically as a Base (you can supply a pointer or >reference to a Derived object where a Base object is expected), >because members and friends have the necessary access. If instead of >private inheritance you use protected inheritance, then the IS-A >relationship is additionally visible to further-derived classes, which >means subclasses can also make use of the polymorphism. > > >Again, to repeat: I am not recommending protect inheritance as sound >engineering practice. I currently believe that "protected inheritance >is necessary" directly implies that the class must have at least two >responsibilities, and hence the class should be factored. In other >words, "protected inheritance is necessary" implies an improvable >design. ------------------------------------------------------------------- (Private correspondence, 22 Feb 99) TRIBBLE: David R. Tribble (dtribble@technologist.com) One possible use for protected inheritance I came across recently is to declare a class which inherits a struct (typically a POD type) in a protected way. This allows the class to operate with full type safety, data hiding, etc., which is something the original struct probably didn't have. Since the struct is inherited as protected, this also has the benefit of allowing the derived class to act as a base class for further derived subclasses. Example: #include // Declares struct tm class MyTime: protected std::tm { public: ...ctor, dtor, accessors, member funcs, etc. ...which encapsulate struct std::tm functionality }; Struct tm doesn't have any of the benefits of object-oriented design (no restricted member access, no data hiding, no member functions, etc.). Class MyTime embodies all of the members of struct tm, but makes them inaccessible to outside clients; the class can also add member functions and so forth, in effect embuing the struct with object-oriented design constraints. The intend would be to use class MyTime instead of struct tm. And since the members of MyTime are protected they are still accessible to other classes which inherit class MyTime, which makes MyTime a suitable base class. In other words, protected inheritance might be a useful technique for wrapping object-oriented classes around simple, non-object-like structs.