FAQ 17.08 How can a class Y get the bits of an existing class X without making Y a kind-of X?There are three alternatives. The preferred solution is normal composition, also known as has-a. But in some cases private inheritance should be used, and in a few cases, protected inheritance should be used. Here is the class X that will be used in each of the three following examples. class X { public: void f() throw(); void g() throw(); private: int a_; float b_; }; Here is the C++ syntax for composition (that is, Y has-a X). This is the preferred solution. class Y1 { public: void f() throw(); protected: X x_; <-- 1 }; void Y1::f() throw() { x_.f(); } <-- 2
Here is the C++ syntax for private inheritance, which is semantically the same as has-a but with an increased ripple effect (changes to the protected: part of X can break the private derived class Y2). This is the second of the three alternatives. class Y2 : private X { <-- 1 public: using X::f; <-- 2 };
Here is the C++ syntax for protected inheritance, which is semantically the same as has-a but with an even greater ripple effect than private inheritance (changes to the protected: part of X can break the protected derived class Y3 and can also break any classes derived from Y3). This is the last of the three alternatives. class Y3 : protected X { <-- 1 public: using X::f; <-- 2 };
In all three cases, a Y object has a X object, and users of Y are unaware of any relationship between Y and X. For example, user code will not break if the relationship between Y and X changes or even is eliminated. See FAQ 37.01 for more information on private and protected inheritance. |