C++ inheritance

Protection levels

Let's start with a base class and one derived class. What we want to do first is take a look at the differences between public, protected and private. Here is a small program that will not compile.
// base.cpp - illustrate some inheritance features
#include <iostream.h>

class base
{
public:
	int apublic;
protected:
	int bprotected;
private:
	int cprivate;

public: base(){
		apublic = 0;
		bprotected = 0;
		cprivate = 87;
	}

	void show(){
		cout << "apublic = " << apublic << ", bprotected = " << bprotected <<
			", cprivate = " << cprivate << endl;
	}

};

class derived1 : public base
{
public:
	derived1(){
		bprotected = 45;
		cprivate = 47;
	}
};

void main(){
	derived1 d;
	d.bprotected = 55;
	d.show();
}



When we try to compile it, we get these messages.
Compiling...
base.cpp
C:\CLASSES\datastruc\base\base.cpp(31) : error C2248: 'cprivate' : cannot access private member declared in class 'base'
        C:\CLASSES\datastruc\base\base.cpp(11) : see declaration of 'cprivate'
C:\CLASSES\datastruc\base\base.cpp(37) : error C2248: 'bprotected' : cannot access protected member declared in class 'base'
        C:\CLASSES\datastruc\base\base.cpp(9) : see declaration of 'bprotected'
Error executing cl.exe.

base.obj - 2 error(s), 0 warning(s)

The derived class object can access the protected member of its parent, but not the private member. The main() function cannot access the protected member of the base class.

You should notice the little popup you get when you start to type "d." in the main:

Notice the icons attached to the various members that indicate their level of protection.

Ambiguity

Now let's get into multiple inheritance. Here's a modified version of the program that fixes the preceding errors, but introduces a new one.
// base.cpp - illustrate some inheritance features
#include <iostream.h>

class base
{
public:
	int apublic;
protected:
	int bprotected;
private:
	int cprivate;

public:
	base(){
		apublic = 0;
		bprotected = 0;
		cprivate = 87;
	}

	void show(){
		cout << "apublic = " << apublic << ", bprotected = " << bprotected <<
			", cprivate = " << cprivate << endl;
	}

};

class derived1 : public base
{
public:
	derived1(){
		bprotected = 45;
	}
};

class derived2 : public base
{
public:
	derived2(){
		bprotected = 39;
	}
};

class underling : public derived1, public derived2
{
public:
	underling(){
	}
};

void main(){
	underling u;
	u.show();
}



This time we get the following messages.
--------------------Configuration: base - Win32 Debug--------------------
Compiling...
base.cpp
C:\CLASSES\datastruc\base\base.cpp(52) : error C2385: 'underling::show' is ambiguous
C:\CLASSES\datastruc\base\base.cpp(52) : warning C4385: could be the 'show' in base 'base' of base 'derived1' of class 'underling'
C:\CLASSES\datastruc\base\base.cpp(52) : warning C4385: or the 'show' in base 'base' of base 'derived2' of class 'underling'
Error executing cl.exe.

base.obj - 1 error(s), 2 warning(s)

The trouble is that the structure we have tried to build looks like this.
There are two instances of the base class, and each one has its own show() function. Which one did we mean? The compiler can't guess which, so it tells us that we have an ambiguous reference.

One way to fix this ambiguity is to specify exactly which show() function we want by adding a qualifier: The modified main() looks like this.


void main(){
	underling u;
	cout << "Through the derived1 superclass\n";
	u.derived1::show();
	cout << "Through the derived2 superclass\n";
	u.derived2::show();
}

Now the program will execute, and we get
Through the derived1 superclass
apublic = 0, bprotected = 45, cprivate = 87
Through the derived2 superclass
apublic = 0, bprotected = 39, cprivate = 87

Virtual base classes

In the situation above, when a derived1 instance was constructed, one instance of the base class was constructed. When a derived2 instance was constructed, another instance of the base class was constructed. In some problems, we might want only one instance of the base class. C++ lets us specify this by making the inheritance virtual. The meaning of the word virtual in the next version of the program is that only one instance of the base class will be constructed.
// base.cpp - illustrate some inheritance features
#include <iostream.h>

class base
{
public:
	int apublic;
protected:
	int bprotected;
private:
	int cprivate;

public:
	base(){
		apublic = 0;
		bprotected = 0;
		cprivate = 87;
	}

	void show(){
		cout << "apublic = " << apublic << ", bprotected = " << bprotected <<
			", cprivate = " << cprivate << endl;
	}

};

class derived1 : public virtual base
{
public:
	derived1(){
		bprotected = 45;
	}
};

class derived2 : public virtual base
{
public:
	derived2(){
		bprotected = 39;
	}
};

class underling : public derived1, public derived2
{
public:
	underling(){
	}
};

void main(){
	underling u;
	u.show();

}



We can get by in the main() without qualifying show() because now there is only one show(). The structure we have built now only has one instance of the base class, like this.
The output of the program is
apublic = 0, bprotected = 39, cprivate = 87