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

Contents of InheritanceLecture
- Inheritance
- Overriding Parent's Function
- Overriding Parent's Data
- Accessing Parents Private Data/Functions
- Base Class Initialization
- Public, Protected, Private Base Classes
- Protected Inheritance
- Private Inheritance
- Exempting Individual Members
- Inheritance is not Overloading
- Copy Constructors and Inheritance
- Multiple Inheritance
- Name Ambiguity
- Virtual Base Class
- Inheritance and Types
- Virtual Functions
- Virtual and Memory Leaks
- More Assignment Problems In C++
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 {};
- Base (Parent, or Super) Class
- Class which is inherited from
- Derived (Child, or Sub) Class
- 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";
}
#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
#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
}
#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
}
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
- 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
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
}
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
}
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
};
#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
}
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
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
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;
#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
- Virtual base class constructors are invoked first.
- Multiple Virtual base class constructors are invoked in the order they
appear in the class definition.
- Nonvirtual base class constructors are invoked in the order they appear in
the class definition.
- Member class constructors are invoked in the order of member class objects
are declared.
- Destructors are called in reverse order of the constructors.
#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
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
- A derived class object, reference, or pointer is implicitly converted
into its public base class type.
- A pointer of any class type is implicitly converted into a pointer of
type void*
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
}
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
}
#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 "
}
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'
}