we have discussed the virtual inhertiance in general in the post - C++ - virtual inheritance?. In this post we are not going to discuss the theory but instead we are going to show you an example so that hopefully you can get a feel of how the virtual inheritance can be useful in real world.
?
Let's see we are devising libraries classes , the base classes is a Array<Type> class, and we want to add more functionality based on the base class. ?So we are going to add some range checking abilility and then we are going to add a sorted functions. here is the code.?
?
/** * virtual inheritance example * in this example, we are going to discuss the topic of multiple inheritance in an example * * */ template <class Type> class Array; template <class Type> ostream& operator << (ostream&, const Array<Type>&); template <class Type> class Array { static const int ArraySize = 12; public: explicit Array(int sz = ArraySize) { init (0, sz); } Array(const Type *ar, int sz) { init(ar, sz); } Array(const Array &ia) { init(ia.ia, ia.size()); } virtual ~Array() { delete[] ia; } Array& operator= (const Array&); int size() { return _size; } virtual void grow(); virtual void print (ostream& = cout); // program technique, in order to allow for better performance, // since we are going to allow user to polymorphically //retrieve the element at a specified index, // in order not to sacrifise the performance, we are making some helper class which is called // at() which can be inlined. Type at(int ix) const { return ia[ix]; } virtual Type& operator[] (int ix) { return ia[ix]; } virtual void sort(int, int); virtual int find(Type ); virtual Type min(); virtual Type max(); protected: void swap(int , int); void init(const Type* , int); int _size; Type * ia; private: }; template <class Type> class Array_RC : public virtual Array<Type> { public: // it is wrong to write as // Array_RC(int sz = ArraySize) : Array (sz) {} any reference to the base template base class type specifier must be fully // qualitified with its formal paramters list. Array_RC(int sz = ArraySize) : Array<Type> (sz) {} Array_RC(const Array_RC& r) ; Array_RC(const Type * ar, int sz); Type& operator[] (int ix); protected: private: }; #include <assert.h> template <class Type> Array_RC<Type>::Array_RC(const Array_RC<Type> &r) : Array<Type>(r) {} template<class Type> Array_RC<Type>::Array_RC(const Type * ar, int sz) : Array<Type>(ar, sz) {} template <class Type> Type& Array_RC<Type>::operator[] (int ix) { assert(ix >= 0 && ix < Array<Type>::_size); return ia[ix]; } template <class Type> class Array_Sort : public virtual Array<Type> { public: Array_Sort(const Array_Sort<Type> &); Array_Sort(const int sz = Array<Type>::ArraySize) : Array<Type>(sz) { clear_bit(); } Array_Sort(const Type* arr, int sz) :Array<Type>(arr, sz) { sort(0, Aray<Type>::_size - 1); clear_bit(); } Type operator[] (int ix) { set_bit(); return ia[ix]; } void print(ostream& os = cout ) { check_bit(); Array<Type>::print(os); } Type min() { check_bit(); return ia[0]; } Type max() { check_bit(); return ia[Array<Type>::_size - 1]; } bool is_dirty() const { return dirty_bit; } int find(Type); void grow(); protected: void set_bit() { dirty_bit = true; } void clear_bit() { dirty_bit = true; } void check_bit() { if (dirty_bit) { sort(0, Array<Type>::_size); clear_bit(); } } private: }; template <class Type> Array_Sort<Type>::Array_Sort(const Array_Sort<Type> &as) { // note: as.check_bit() does not work // -- see explanation below if (as.is_dirty()) { sort(0, Array<Type>::_size - 1 ); } clear_bit(); } /** this is a very typical implemenation of the divide 2 search */ template <class Type> int Array_Sort<Type>::find(Type value) { int low = 0; int high = Array<Type>::_size - 1; check_bit(); while (low <= high) { int mid = (low + high ) / 2; if (val == ia[mid]) return mid; if (val < ia[mid]) high = mid - 1; else low = mid + 1; } return -1; } /** * now we are going to make a class that shall inherits both the * Array_Sort and the Array_RC * and the new class would be named as * Array_RC_S * */ template <class Type> class Array_RC_S : public Array_RC<Type>, public Array_Sort<Type> { public: Array_RC_S(int sz = Array<Type>::ArraySize) : Array<Type>(sz) { Sort(0, Array<Type>::_size - 1); clear_bit(); } Array_RC_S(const Array_RC_S<Type> & rca) : Array<Type>(rca) { sort(0, Array<Type>::_size -1 ); clear_bit(); } Array_RC_S(const Type* arr, int sz) : Array<Type> (rca) { sort(0, Array<Type>::_size - 1); clear_bit(); } Type& operator[] (int index) { set_bit(); return Array_RC<Type>::operator[] (index); } };?