Thursday 30 July 2009

Virtual Base class Inheritance


Came across this interesting case of multiple base class inheritance which can result in compilation errors.

Figure above demonstrates the ambiguity that can occur in diamond inheritance. The program defines class Base, which contains pure virtual function print. Classes DerivedOne and DerivedTwo each publicly inherit from class Base and override the print function. Class DerivedOne and class DerivedTwo each contain what the C++ standard refers to as a base-class subobject—i.e., the members of class Base in this example.

Class Multiple inherits from both classes DerivedOne and DerivedTwo. In class Multiple, function print is overridden to call DerivedTwo’s print.

Function main declares objects of classes Multiple, DerivedOne and DerivedTwo. main also declares an array of Base * pointers. Each array element is initialized with the address of an object. An error occurs when the address of both—an object of class Multiple—is assigned to array[ 0 ]. The object both actually contains two subobjects of type Base, so the compiler does not know which subobject the pointer array[ 0 ] should point to, and it generates a compilation error indicating an ambiguous conversion.

The problem of duplicate subobjects is resolved with virtual inheritance. When a base class is inherited as virtual, only one subobject will appear in the derived class—a process called virtual base-class inheritance.



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example showing virtual base class inheritance
//http://www.deitel.com/articles/cplusplus_tutorials/20060225/virtualBaseClass/index.html

#include <iostream>
using std::cout;
using
std::endl;

// class Base definition
class Base
{

public
:
virtual
void print() const = 0; // pure virtual
}; // end class Base

// class DerivedOne definition
//class DerivedOne : public Base - REF1
class DerivedOne : virtual public Base
{

public
:
// override print function
void print() const
{

cout << "DerivedOne\n";
}
// end function print
}; // end class DerivedOne

// class DerivedTwo definition
//class DerivedTwo : public Base - REF2
class DerivedTwo : virtual public Base
{

public
:
// override print function
void print() const
{

cout << "DerivedTwo\n";
}
// end function print
}; // end class DerivedTwo

// class Multiple definition
class Multiple : public DerivedOne, DerivedTwo
{

public
:
// qualify which version of function print
void print() const
{

DerivedTwo::print();
}
// end function print
}; // end class Multiple

int
main()
{

Multiple both; // instantiate Multiple object
DerivedOne one; // instantiate DerivedOne object
DerivedTwo two; // instantiate DerivedTwo object
Base *array[ 3 ]; // create array of base-class pointers

array[ 0 ] = &both; // ERROR - ambiguous if REF1 and REF2 used
array[ 1 ] = &one;
array[ 2 ] = &two;

// polymorphically invoke print
for ( int i = 0; i < 3; i++ )
array[ i ] -> print();

return
0;
}
// end main

The output is as follows:


1 comment:

  1. Hi! how can you do an upcasting and downcasting beetwen derived classes? and then call print using casting only...

    ReplyDelete