TITLE: avoiding multiple method calls due to multiple inheritance (Newsgroups: comp.lang.c++.moderated, 15 May 98) HARLEY: David Harley > Has anyone an elegant solution to the following design problem I > keep bumping into? Suppose you have the following inheritance > tree, with A a virtual class: > > A > / \ > B C > \ / > D > > Suppose A defines virtual function f(). What I often have is > a situation where each subclass will suppliment f() with some extra > code, so for example: > > B::f() { A::f(); } > > Likewise for C. The problem begins with D: > > D::f() { B::f(); C::f(); < do some extra stuff> } > > The result of course is that A::f() gets called twice for each call > to D::f(). What I want is a _single_ call to each method of every > class in the inheritance tree. > > Now suppose there are 100 virtual methods, you never know who > is going to stick another one in, or exactly how complicated the > tree is going to get, and that maintainability is a big issue. > How do you make this structure extensible without having to > touch any existing source? Any ideas? > SRINIVAS: "Srinivas Vobilisetti" This issue is discussed in the The C++ Programming Language 2nd edition by Stroustrup under multiple inheritance. It maybe discussed in the 3rd edition too, but I am not sure. It goes like this: class A { protected: void _f(); public: virtual void f() { _f(); } }; class B : virtual public A { protected: void _f(); public: virtual void f() { A::_f(); _f(); } }; class C : virtual public A { protected: void _f(); public: virtual void f() { A::_f(); _f(); } }; class D : public B, public C { protected: void _f(); public: virtual void f() { A::_f(); B::_f(); C::_f(); _f(); } }; ABRAHAMS: abrahams@motu.com (David Abrahams) Consider the following design rules. If you redesign your classes this way you will eliminate the problem: 1. (Main rule): Never override a virtual function that is already implemented in a parent class. 2. Never publicly derive from a concrete class 3. All virtual functions should be private, except for pure virtual functions in an abstract base class. 4. (Corrolary to 1&3) Never call anything but the constructor of a base class with explicit qualification. 5. Provide hook functions with empty implementations for extending functionality in derived classes. These rules are an "idealized set". I occasionally break them, but not without a very good reason.