SDSU CS 596 OODP
Inheritance

[To Lecture Notes Index]
San Diego State University -- This page last updated Oct. 28, 1995
----------

Contents of InheritanceLecture

  1. Inheritance
    1. Overriding Parent's Function
    2. Overriding Parent's Data
    3. Accessing Parents Private Data/Functions
    4. Base Class Initialization
    5. Public, Protected, Private Base Classes
      1. Protected Inheritance
      2. Private Inheritance
      3. Exempting Individual Members
    6. Inheritance is not Overloading
    7. Copy Constructors and Inheritance
    8. Multiple Inheritance
      1. Name Ambiguity
    9. Virtual Base Class
    10. Inheritance and Types
  2. Virtual Functions
    1. Virtual and Memory Leaks
    2. More Assignment Problems In C++

Inheritance


Inheritance

#include <iostream.h>

class BankAccount 					// Base Class
{	public :		
		float balance;
		transaction(float amount);                    };

BankAccount::transaction(float amount)
{	balance += amount;}


class CheckingAccount : public BankAccount 	// Derived Class
{
	public:
		check(float amount);
};


CheckingAccount::check(float amount)
{
	transaction(-amount);
}

main()
{
	CheckingAccount me;

	me.balance = 100;
	me.check(50);
	cout << me.balance << "\n";
}

Inheritance Defined
class Top {};

class Bottom : public Top {};



Class which is inherited from


Class which inherits from one or more Base classes


A derived class inherits all members of its base class except:
constructors
destructors
assignment operators
A derived class inherits but can not access private members of its base class

Access Parent's Members
#include <iostream.h>

class BankAccount 					// Base Class
{	public :		
		float balance;
		void transaction(float amount) {	balance += amount;}
};


class CheckingAccount : public BankAccount 	// Derived Class
{
	public:
		void check(float amount);
		void addInterest();
		
};

void CheckingAccount::check(float amount) {
	transaction( -amount );
}

void CheckingAccount::addInterest() {
	balance += balance * 0.23;
}

main()
{
	CheckingAccount me;

	me.balance = 100;
	me.check(50);
	cout << me.balance << "\n";
}

Overriding Parent's Function

#include <iostream.h>

class BankAccount 					// Base Class
{	public :		
		float balance;
		void transaction(float amount) {	balance += amount;}
};


class CheckingAccount : public BankAccount 	// Derived Class
{
	public:
		void transaction(float amount);
};

void CheckingAccount::transaction(float amount) {
	balance += amount - 0.1;
}


main()
{
	CheckingAccount me;

	me.balance = 100;
	me.transaction(50);
	cout << me.balance << "\n";		// prints 149.9
}

Accessing Parent's Overridden Function
#include <iostream.h>

class BankAccount 					// Base Class
{	public :		
		float balance;
		void print() {	cout << "Parent\n";}
};


class CheckingAccount : public BankAccount 	// Derived Class
{
	public:
		void print();
		
};

void CheckingAccount::print() {
	BankAccount::print();
	cout << " Child\n";
}


main()
{
	CheckingAccount me;
	me.print();
}

Output
Parent
 Child

Overriding Parent's Data

#include <iostream.h>

class BankAccount 					// Base Class
{	public :		
		float balance;
		BankAccount() { balance = 0;}
		void print() {	cout << balance << " Parent\n";}
		void transaction(float amount) {	balance += amount;}
};

class CheckingAccount : public BankAccount 	// Derived Class
{
	public:
		float balance;
		CheckingAccount(int a = 0) { balance = a;}
		void print();
};

void CheckingAccount::print() {
	BankAccount::print();
	cout << balance << " Child\n";
}

main(){
	CheckingAccount me(200);
	me.transaction(100);	
	me.print();
}

Output
100 Parent
200 Child
More Inheritance


class Top
{
	public:
		int SeeMe;
	protected:
		int HideAndSeek;
	private:
		int Hiden;
};

class Bottom :  public Top
{
	public:
		void tryThisOut() 
		{
			SeeMe = 1;
			HideAndSeek = 2;
			Hiden = 3;			// illegal - private member
		}
};

main()
{
	Bottom Barrel;

	Barrel.SeeMe = 10;
	Barrel.HideAndSeek = 20;		// illegal - protected member
	Barrel.Hiden = 30;				// illegal
}

Accessing Parents Private Data/Functions


#include <iostream.h>

class Top{
	public:
		int SeeMe;

		Top() 	{ Hiden = 10; }

		void increaseHiden( int amount ) { Hiden += amount;}

		void print ( ostream& output ) {
			output << "SeeMe " << SeeMe 
				<< " Hiden " << Hiden << endl;
		}

	private:
		int Hiden;
};

class Bottom :  public Top  {
	public:
		void tryThisOut() {
			SeeMe = 1;
			increaseHiden( 23 );
		}
};

main()  {
	Bottom Barrel;

	Barrel.tryThisOut();
	Barrel.print( cout );	// prints SeeMe 1 Hiden 33
}


Base Class Initialization

Simple Base Only

#include <iostream.h>
class Top
{	public:
		int a, b;

		Top()
		{ 	a = 5;	b = 10;
			cout << "In Top\n";
		}
};

class Bottom : public Top
{	public:
		float c;

};


void main()
{	
	Bottom rung;			// prints In Top
}


Top's constructor is not inherited by Bottom.
Bottoms default constructor calls Top's constructor.

Base Class Initialization
Simple Both Classes

#include <iostream.h>
class Top
{	public:
		int a, b;

		Top()
		{ 	a = 5;	b = 10;
			cout << "In Top\n";
		}
};

class Bottom : public Top
{	public:
		float c;
		Bottom() { cout << "In Bottom\n";}
};



void main()
{	
	Bottom rung;

}

Output

In Top
In Bottom

Base Class Initialization
Derived Class Only
#include <iostream.h>
class Top
{	public:
		int a, b;
};


class Bottom : public Top
{	public:
		float c;
		Bottom() { cout << "In Bottom\n";}
};


void main()
{	
	Bottom rung;

}

Output

In Bottom


Base Class Initialization
Be careful

#include <iostream.h>
class Top
{	public:
		int a, b;

		Top(int x, int y)
		{ 	a = x;	b = y;
			cout << "In Top\n";
		}

};

class Bottom : public Top
{	public:
		float c;
		Bottom() { cout << "In Bottom\n";}	// Compile error
};


void main()
{	
	Bottom rung;			
}

Base Class Initialization

#include <iostream.h>
class Top
{	public:
		int a, b;

		Top(int x, int y)
		{ 	a = x;	b = y;	cout << "In Top\n";}
};

class Bottom : public Top
{	public:
		float c;
		Bottom(float w, int x, int y);
};

Bottom::Bottom(float w, int x, int y):  Top( x, y )
{
	cout << "In Bottom\n";
	c = w;
	a = 10;				// Bad style
}

main()  {	
	Bottom rung(1, 2, 3);
	cout << rung.c << "\n" << rung.a << "\n";
}

Output
In Top
In Bottom
1
10

Base Class Initialization
Don't Initialize Parents Data in Initialization Phase

#include <iostream.h>
class Top
{	public:
		int a, b;

		Top( int x = 0, int y =5 )
		{ 	a = x;	b = y;	cout << "In Top\n";}
};

class Bottom : public Top
{	public:
		float c;
		Bottom(float w, int x, int y);
};

Bottom::Bottom(float w, int x, int y):   a(4)
								// compile error
{
	cout << "In Bottom\n";
	c = w;
}

main()  {	
	Bottom rung(1, 2, 3);
	cout << rung.c << "\n" << rung.a << "\n";
}

Hiding Constructors - Why?

#include <iostream.h>

class Top {
	public :
		int Hi;

	protected:
		Top(int a = 0) { Hi = a;}
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) { Bye = b;}

		void print() { cout << Hi << " " << Bye << endl; }
};

main() {
	//Top 	CanNotCreate;	compile error

	Bottom 		OK( 10, 10 );

	Copy.print();
}

Output
10 10

Even More Inheritance

Public, Protected, Private Base Classes


Public
inherited members of a public base class maintain access level in a derived class


Protected
inherited public and protected members of a protected base class become protected members in a derived class
protected base classes are new to C++ version 3.0

Private
inherited public and protected members of a private base class become private members in a derived class

Protected Inheritance


class Top
{
	public:
		int SeeMe;
	protected:
		int HideAndSeek;
	private:
		int Hiden;
};

class Bottom :  protected Top
{
	public:
		void tryThisOut() 
		{
			SeeMe = 1;
			HideAndSeek = 2;
			Hiden = 3;			// illegal - private member
		}
};

main()
{
	Bottom Barrel;

	Barrel.SeeMe = 10;			// illegal - protected member
	Barrel.HideAndSeek = 20;		// illegal - protected member
	Barrel.Hiden = 30;				// illegal - protected member
}

Private Inheritance


class Top
{
	public:
		int SeeMe;
};

class Middle : private Top
{
	public:
		void WatchThis()
		{
			SeeMe = 10;}			// Ok is private member
};

class Bottom :  public Middle
{
	public:
		void tryThisOut() 
		{
			SeeMe = 1;	// illegal - private member of base class
		}
};

main()
{
	Bottom Barrel;

	Barrel.SeeMe = 10;			// illegal - private member
}

Exempting Individual Members


class Top
{
	public:
		int SeeMe;
		int HideMe;
	protected:
		int ProtectMe;
};

class Middle : private Top
{	public:
		Top::SeeMe;
	protected:
		Top::ProtectMe;
};

class Bottom :  public Middle
{	public:
		void tryThisOut() 
		{
			SeeMe = 1;				// Ok
			HideMe= 1;	// illegal - private member of base class
			ProtectMe= 1;			// Ok 
		}
};

main()
{	Bottom Barrel;
	Barrel.SeeMe = 10;			// OK
	Barrel.HideMe= 10;			// illegal - private member
	Barrel.ProtectMe= 10;			// illegal - private member
}

Exempting Individual Members
Can't Exempt Higher Than Original Access
class Top
{
	public:
		int SeeMe;
		int HideMe;
	protected:
		int ProtectMe;
};

class Middle : protected Top
{	public:
		Top::ProtectMe;		// error
};



Inheritance is not Overloading


#include <iostream.h>

class Top
{
	public:
		void WhatIsMyName(char *string) {	cout << "Roger\n";};
};

class Bottom :  public Top
{	
	public:
		void WhatIsMyName(int a) {	cout << "Whitney\n";};

		void WhereAmI(char *string)  {	cout << "Here\n";}

		void WhereAmI(int a)  	{	cout << "There\n";}
};

main()
{
	Bottom Pit;
	
	Pit.WhereAmI(5);				// prints There
	Pit.WhereAmI("Hi Mom");		// prints Here
	Pit.WhatIsMyName(5);			// prints Whitney
	Pit.WhatIsMyName("Hi Dad");	// illegal
}

Copy Constructors and Inheritance

Parent Has Copy, Child Does Not
#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}

		Top( const Top& object ) { 
			Hi = object.Hi + 5; 
			cout << " Parent Hi" << Hi << endl;
		};
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) { Bye = b;}

		void print() { cout << Hi << " " << Bye << endl; }
};

main() {
	Bottom 		Start( 10, 10 );
	Bottom 		Copy = Start;

	Copy.print();
}

Output
Parent Hi15
15 10

Copy Constructors and Inheritance
Child Has Copy, Parent Does Not
#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) { Bye = b;}

		Bottom ( const Bottom& object ) {
			Bye = object.Bye + 10;
			cout << "In Child \n";
		}
		void print() { cout << Hi << " " << Bye << endl; }
};

main() {
	Bottom 		Start( 10, 10 );
	Bottom 		Copy = Start;

	Copy.print();
}

Output
In Child
0 20
Copy Constructors and Inheritance
Better Child Copy???
#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) { Bye = b;}

		Bottom ( const Bottom& object ) {
			Bye = object.Bye + 10;
			Hi = object.Hi;
			cout << "In Child \n";
		}
		void print() { cout << Hi << " " << Bye << endl; }
};

main() {
	Bottom 		Start( 10, 10 );
	Bottom 		Copy = Start;

	Copy.print();
}

Output
In Child
10 20
Copy Constructors and Inheritance
Child Has Copy, Parent Has Copy
#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}
		Top( const Top& object ) { 
			Hi = object.Hi + 5; 
			cout << " Parent Hi" << Hi << endl;
		};
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) { Bye = b;}

		Bottom ( const Bottom& object ) : Top( object ) {
			Bye = object.Bye + 10;
			cout << "In Child \n";
		}
		void print() { cout << Hi << " " << Bye << endl; }
};

main() {
	Bottom 		Start( 10, 10 );
	Bottom 		Copy = Start;
	Copy.print();
}
Output
Parent Hi15
In Child
15 20

Multiple Inheritance


class Left 
{	public :
		int Sam;
		void printLeft()  { cout << "Sam" << Sam << endl;  };
		Left()		{ Sam = 0;  cout << "Start Left\n"; }
};

class Right 
{	public:
		float Pete;
		void printRight()  { cout << "Pete" << Pete << endl;  }
		Right()		{ Pete = 0;  cout << "Start Right\n"; }
};

class Bottom :  public Left,  public Right 
{	public:
		int Chen;
		void print(); 
		Bottom()		{ Chen = 0;  cout << "Start Bottom\n"; }
};

void Bottom :: print() {
	cout << " Bottom \n";
	printRight();
	printLeft();			};
main() {
	Bottom	ThreeInOne;
	ThreeInOne.Pete = 10;
	ThreeInOne.print();    }
Output
Start Left	Pete10
Start Right	Sam0
Start Bottom
 Bottom 

Name Ambiguity



Which method (getSam) and data (Sam) does Bottom inherit?


redefinition	redefine the operation

renaming	change the name by which a method is invoked

Double Data Member Name

class Left 
{	public :
		int Sam;
		Left()		{ Sam = 0;  cout << "Start Left\n"; }
};

class Right 
{	public:
		int Sam;
		Right()		{ Sam= 20;  cout << "Start Right\n"; }
};

class Bottom :  public Left,  public Right 
{	public:
		int Sam;
		void print(); 
		Bottom()		{ Sam = 30;  cout << "Start Bottom\n"; }
};

void Bottom :: print() {
	cout << "Sam Bottom " << Sam << endl;
	cout << "Sam Right " << Right :: Sam<< endl; 
	cout << "Sam Left " << Left :: Sam<< endl; 
};
main() {
	Bottom	ThreeInOne;
	ThreeInOne.print();    }
Output
Start Left
Start Right
Start Bottom
Sam Bottom 30
Sam Right 20
Sam Left 0

Double Member Name Problems

class Left 
{	public :
		int Sam;
		void print() { cout << Left\n"; }
		Left()		{ Sam = 0;  cout << "Start Left\n"; }
};

class Right 
{	public:
		int Sam;
		void print() { cout << Right\n"; }
		Right()		{ Sam= 20;  cout << "Start Right\n"; }
};

class Bottom :  public Left,  public Right 
{	public:
		Bottom()		{ Sam = 30;  cout << "Start Bottom\n"; }
};

main() {
	Bottom	ThreeInOne;
	
	ThreeInOne.Sam = 0; 		// Error
	ThreeInOne.Left::Sam = 0; 
	ThreeInOne.Right::Sam = 0; 

	ThreeInOne.print(); 		// Error
	ThreeInOne.Left::print(); 
	ThreeInOne.Right::print(); 

}

If a class inherits two or more variables (functions) of the same name, then any reference to that name must be explicit as to which definition to use.
Common Ancestors

class Top
{	public :		
		int Sam;
		int getSam();         };

class Left : public Top					
{                  };

class Right : public Top	
{	       };

class Bottom :  public Left,  public Right 
{	};

Bottom inherits two copies of Sam and getSam(). So must specify which to use:
Bottom Bother;
Bother.Left::sam = 10;

Virtual Base Class


#include <iostream.h>

class Top
{	public :		
		int Sam = 10;
		int getSam() {return Sam;}                    
};


class Left : virtual  public Top			{	};

class Right : public virtual Top			{	};

class Bottom :  public Left,  public Right 	{	};


main() {
	Bottom OfTheClass;

	OfTheClass.getSam();
}
	

Virtual Bases, Constructors, Destructors

#include <iostream.h>

class A 				{ public : A() {cout << "A\n" ;}	};

class B : public A 		{ public : B() {cout << "B\n" ;}	}; 

class C : virtual public B { public : C() {cout << "C\n" ;}  };

class Confused { 
	public : 
		Confused() { cout << "Confused\n" ;}  };

class Right 	{
	 public : 
		Right() {cout << "Right\n" ;}	};

class Left 	{
	 public : 
		Left() {cout << "Left\n" ;}		};

class Test :	public Right,
			public C,
			public virtual Left   {
	public: 
		Confused State;
		Test() { cout << "Test\n"; }; };

main () {
	Test me;
	cout << "Done" << endl;
};

Output
A	Test
B	Done
Left
Right
C
Confused

Inheritance and Types


If a class is a type then a subclass is a subtype



class Top 	{
	public :
		int Hi;    
};


class Bottom :  public Top	 {
	public: 
		int Bye; 
}


main() {
	Top 		A;
	Bottom 		Z;

	A = Z;
}

Space Requirements


C++ Stack Based Memory Allocation
class Top {
	public :
		int Hi;    
};


class Bottom :  public Top	 {
	public: 
		int Bye; 
};


main() {
	Top 		A;
	Bottom 		Z;

	A = Z; 		// * Strip all extra data and methods from Z
				//  A.Bye does not exist

	Z = A;		// * Should this be allowed? Compile Error
}


Inheritance and Type
Implicit Conversion of Classes



Implicit Conversion Up

#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}    
		void print() { cout << Hi << endl;}
};


class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) {
			Bye = b;}
};

void ImplicitConvert( Top Converted) { Converted.print(); }

main() {
	Top 		A( 0 );
	Bottom 		Z( 5, 10 );

	ImplicitConvert( Z );
	A = Z; 		
	A.print();
}
Output
5
5
Implicit Conversion Up, Wrong Base Type

#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}    
		void print() { cout << Hi << endl;}
};


class Bottom :  protected Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) {
			Bye = b;}
};

void ImplicitConvert( Top Converted) { Converted.print(); }
	

main() {
	Top 		A( 0 );
	Bottom 		Z( 5, 10 );

	ImplicitConvert( Z );	// Compile Error
	A = Z; 				// Compile Error
	A.print();
}

Implicit Conversion Down

#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}    
		void print() { cout << Hi << endl;}
};


class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) {
			Bye = b;}
};

void ImplicitConvert( Bottom Converted) { Converted.print(); }
	

main() {
	Top 		A( 0 );
	Bottom 		Z( 5, 10 );

	ImplicitConvert( A );	// Compile Error
	Z = A; 				// Compile Error
	A.print();
}

Explicit Conversion Down
Some Compilers Don't Do this (CC, g++)

#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}    
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) {
			Bye = b;}

		void print() { cout << Hi << " " << Bye << endl; }
};

void ImplicitConvert( Bottom Converted) { Converted.print(); }

void main() {
	Top 		A( 1 );
	Bottom 		Z( 5, 10 );

	ImplicitConvert( (Bottom)A );	
	Z = (Bottom)A; 	
	Z.print();
}

Output
1 5
1 1


Convert Down via Constructor
#include <iostream.h>

class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}    
		void print() { cout << Hi << endl;}
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom(int a = 5, int b = 10) : Top(a) { Bye = b;}

		Bottom( Top object ) {
			Hi = object.Hi;
			Bye = 0; }
		void print() { cout << Hi << " " << Bye << endl; }
};

void ImplicitConvert( Bottom Converted) { Converted.print(); }

main() {
	Top 		A( 0 );
	Bottom 		Z( 5, 10 );

	ImplicitConvert( A );	
	Z = A; 				
	Z.print();
}
Output
0 0
0 0
Dynamic Memory Allocation

main() {
	Top* 		A = new Top;
	Bottom* 	Z = new Bottom;

	
A = Z;		// A->Bye does exist

A and Z are now aliases for the same object!

Can't Access Bye From Top Pointer

#include <iostream.h>
class Top {
	public :
		int Hi;    
};


class Bottom :  public Top	 {
	public: 
		int Bye; 
};


main() {
	Top* 		A = new Top;
	Bottom* 	Z = new Bottom;
	
	Z->Bye = 5;
	A = Z;

	cout << A->Bye << endl;		// compile error
}


Inheritance and Type
Continued
#include <iostream.h>
class Top
{
	public:
		void WhatIsMyName() { cout << "Roger\n";}
};

class Bottom :  public Top
{	
	public:
		void WhatIsMyName() {	cout << "Whitney\n";}
};

main()
{
	Bottom pit, barrel;
	Top tar, dog;
	
	pit.WhatIsMyName();			// prints Whitney
	tar.WhatIsMyName();			// prints Roger

	tar = pit;

	tar.WhatIsMyName();			// prints Roger

	dog = barrel;
	dog.WhatIsMyName();			// prints Roger
}

Virtual Functions


class Top {
	public:
		virtual void WhatIsMyName() {	cout << "Roger\n"; }
};

class Bottom :  public Top  {	
	public:
		void WhatIsMyName() {	cout << "Whitney\n";}
};

main()
{
	Bottom* pit = new Bottom;
	Top* tar  = new Top;
	Top	Dog;
	
	pit->WhatIsMyName();			// prints Whitney
	tar->WhatIsMyName();			// prints Roger

	tar = pit;
	Dog = *pit;

	tar->WhatIsMyName();			// prints Whitney
	Dog.WhatIsMyName();			// prints Roger
}

The redefinition of a virtual function in a derived class must match exactly the name, signature, and return type of the base class instance. The use of the keyword in the derived class in not required. In all subclasses the function will be virtual. It does help indicate which functions are virtual.
Can Access Bye From Top Pointer
#include <iostream.h>
class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}

		virtual void  print(ostream& out) {
			out << "Hi " << Hi << endl;}    
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom ( int a = 5) { Bye = a;}

		virtual void  print(ostream& out) {
			out << "Hi " << Hi << endl;
			out << "Bye " << Bye << endl;}    

};

main() {
	Top* 		A = new Top;
	Bottom* 	Z = new Bottom;
	
	A->print( cout );
	A = Z;
	A->print( cout );
}
Output
Hi 0
Hi 0
Bye 5

Parent Needs Virtual - Must have function
#include <iostream.h>
class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom ( int a = 5) { Bye = a;}

		virtual void  print(ostream& out) {
			out << "Hi " << Hi << endl;
			out << "Bye " << Bye << endl;}    
};

main() {
	Top* 		A = new Top;
	Bottom* 	Z = new Bottom;
	
	A->print( cout );		// Compile Error
	A = Z;
	A->print( cout );		// Compile Error
}

Parent Needs Virtual
Must Declare Virtual in Parent
#include <iostream.h>
class Top {
	public :
		int Hi;
		Top(int a = 0) { Hi = a;}

		void print(ostream& out) {
			out << "Hi " << Hi << endl;}    
};

class Bottom :  public Top	 {
	public: 
		int Bye; 
		Bottom ( int a = 5) { Bye = a;}

		virtual void  print(ostream& out) {
			out << "Hi " << Hi << endl;
			out << "Bye " << Bye << endl;}    
};

main() {
	Top* 		A = new Top;
	Bottom* 	Z = new Bottom;
	
	A->print( cout );
	A = Z;
	A->print( cout );
}

Output
Hi 0
Hi 0
Pure Virtual Functions

No objects can be made from a class containing pure virtual functions

class Abstract {
	public:
		virtual void NotHere() = 0;
		virtual void NotThere() = 0;
		virtual void NoWhere() = 0;
};


class Concrete : public Abstract {
	public:
		virtual void NotHere();
		virtual void NotThere();
		virtual void NoWhere();
};

void Concrete::NotHere() { }		// null instance

void Concrete::NotThere()  {
	error("Calling undefined virtual NotThere in Concrete");
}

void Concrete::NoWhere() {
	// put some reasonable code here
}

Virtual Functions and Protection Level

#include <iostream.h>

class Top {
	public:
		virtual void DontDoThisToMe() {cout << "Top\n";};
};


class Middle : public Top {
	private:
		virtual void DontDoThisToMe() {cout << "Middle\n";};
};

main() {
	Middle* WontWork = new Middle;
	Top* Works;

	WontWork->DontDoThisToMe();	// compile error

	Works = WontWork;

	Works ->DontDoThisToMe();		// prints Middle

}


Virtual and Memory Leaks


#include <iostream.h>

class Top {
	public :
		int* Hi;

		Top(int a = 0) { Hi =  new int( a );}

		~Top()  	{ delete Hi;  cout << "destroy Hi\n"; }

		virtual void print() { cout << *Hi << endl; }

};

class Bottom :  public Top	 {
	public: 
		int* Bye; 

		Bottom(int a = 5, int b = 10) : Top(a) { Bye = new int( b );}

		~Bottom()  	{ delete Bye;  cout << "destroy Bye\n"; }

		void print() { cout << *Hi << " " << *Bye << endl; }
};

main() {
	Top* Problem = new Bottom( 1, 2 );

	Problem->print();
	delete Problem;
	cout << " Who deletes Bye?\n";
}

Output
1 2
destroy Hi
 Who deletes Bye?

Virtual and Memory Leaks - Use Virtual Destructors

#include <iostream.h>

class Top {
	public :
		int* Hi;

		Top(int a = 0) { Hi =  new int( a );}

		virtual ~Top()  	{ delete Hi;  cout << "destroy Hi\n"; }

		virtual void print() { cout << *Hi << endl; }
};

class Bottom :  public Top	 {
	public: 
		int* Bye; 

		Bottom(int a = 5, int b = 10) : Top(a) { Bye = new int( b );}

		~Bottom()  	{ delete Bye;  cout << "destroy Bye\n"; }

		void print() { cout << *Hi << " " << *Bye << endl; }
};

main() {
	Top* Problem = new Bottom( 1, 2 );

	Problem->print();
	delete Problem;
	cout << "Bye is gone\n";
}

Output
1 2
destroy Bye
destroy Hi
Bye is gone

When Virtual is Static

* Function is called through an object

* Function is called using class scope operator

* Function is called in constructor or destructor of base class

#include <iostream.h>

class ThisIsEasy {
	public:
		virtual void HappyTimes() {cout << "are here ";}
		ThisIsEasy() {HappyTimes();}
};

class DownHere : public ThisIsEasy {
	public:
		virtual void HappyTimes() {cout << "again ";}
		DownHere() {HappyTimes();}
};

main() {
	ThisIsEasy	Really;			// prints "are here "	
	ThisIsEasy*	SomeTimes 
				= new DownHere;	// prints "are here again"

	Really = *SomeTimes ;
	Really.HappyTimes();			// prints "are here "

	SomeTimes->ThisIsEasy::HappyTimes();  // prints "are here "
}
	

More Assignment Problems In C++


class Top
{       public :
                virtual void see() ;      };

class Bottom :  public Top
{       public:
                virtual void see() ;  };


void Top::see()   {  printf("Hi Mom"); };

void Bottom::see() {  printf("Hi Dad");  };


void Why( Top   Gun)            // pass-by-value
{ 	Gun.see();    };

void Me(  Top&   Gun )          // pass-by-reference
{	Gun.see();	};


main()
{
        Bottom  Trouble;

        Why(Trouble);			// prints 'Hi Mom'

        Me(Trouble);				// prints 'Hi Dad'
}
----------