Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!olivea!decwrl!sgi!shinobu!odin!sgi.com!linton From: linton@sgi.com (Mark Linton) Newsgroups: comp.lang.c++ Subject: Re: private base classes (was Nonvirtual base classes in MI) Message-ID: <1991Feb8.220931.251@odin.corp.sgi.com> Date: 8 Feb 91 22:09:31 GMT References: <1174@zinn.MV.COM> <64173@brunix.UUCP> Sender: news@odin.corp.sgi.com (Net News) Reply-To: linton@sgi.com (Mark Linton) Organization: sgi Lines: 42 In article <64173@brunix.UUCP>, sdm@cs.brown.edu (Scott Meyers) writes: |> In article <1174@zinn.MV.COM> mjv@objects.mv.com (Michael J. Vilot) writes: |> | I agree with Keith, and with Tom Cargill, that private base classes can be |> | transformed into class members. There may be some minor performance |> | differences between the two, but I suspect on average it's a wash. |> |> No no no. You lose virtual functions when you turn inheritance into member |> containment. There is a conceptual distinction between the following: |> |> A has a member B ==> A "has a" B (or A "contains a" B) |> A publicly inherits from B ==> A "is a" B |> A privately inherits from B ==> A "is implemented in terms of a" B |> |> Private inheritance is a convenient way to share code when there is no |> other conceptual relationship between two classes. I usually call this |> "code stealing." When stealing the code in another class, you often have |> to do some class specific stuff; this is where virtual functions come in. |> The member functions in the (private) base class can call virtual functions |> to do the customization. This won't work with member objects, because they |> have no way of knowing what they're a part of. The case you refer to is pretty pathological. I'll use the names Base and Derived instead of your B and A. Since Derived privately inherits from Base, the only place you can call a Base method from a Derived object is in Derived itself. Then Base::method calls a virtual on Base that Derived redefines and you end back in a Derived method. Example code is: class Base { virtual void f(); void g(); }; class Derived : private Base { virtual void f(); void h(); }; void A::f() { } void A::g() { shared_before_stuff(); f(); shared_after_stuff(); } void B::f() { ... } void B::h() { g(); } Note that B::f() can't be called directly (except from another B method, of course). You refer to private inheritance as "convenient", but I have never needed the circular control flow above. We don't use it at all in InterViews (about 100K lines of C++). Most examples of code sharing I have seen are better implemented with either separate types or templates (or the macro equivalent). If you have a real example of "convenient" private inheritance, I'd be interested in seeing it.