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);
}
};