multiple inheritance
DESCRIPTION
C ++TRANSCRIPT
Overriding • This phenomena is used in situations where
there is inheritance relationship between classes.
Explanation:
• In the previous example, the derived class DERIVED, has a function fn(), which it has inherited from the base class BASE.
• The derived class can modify the definition of the function fn() which it gets from its base class.
• This process where the base class function is modified
by the derived class, is called overriding.
• The derived class might either add new content, retain the same content or enhance the existing content within the function.
Private
• The private members of a class can be
accessed only by the member functions of
that class.
• private keyword and a “:” symbol are used
to indicate the section of the code, which is
to be treated as private.
private:
Protected
• The protected members of a class can be accessed only by the member functions of that class, and the member functions of the classes derived from it.
• protected keyword and “:” symbol are used to indicate the section of the code, that is to treated as protected.
protected:
Public
• The public members of a class can be
accessed anywhere in the application.
• public keyword and “:” symbol are used to
indicate the section of the code, that is to
treated as public.
• public:
Power of access….
• An object defined outside a class can only access the public members of the class.
• The private members of a class cannot be directly accessed from outside the class.
• For example, the object of the class DERIVED, named d1, cannot directly access the private member variable, c.
• Hence the following code, raises error.
DERIVED d1;
d1.c=34;
Contd…
• This holds true even of the class that is derived from another class.
• Even though the derived class inherits all the data and methods from the base class, the private members of the base class are not accessible within the derived class.
• The idea here is not to compromise on encapsulation implemented through data hiding.
Contd….
• If the derived class, could access the private
members of the base class, then the strong
wall of encapsulation created by data hiding
could be easily broken by creating a dummy
derived class.
• That would defeat the whole purpose of data
hiding and security.
Using Protected Access Specifier…Putting
forward a realistic problem
• Consider the following problem:
• The class “Encryption”, has a private
member function called keycompare().
• A class, called cryptfile, is derived from the
class, Encryption.
• The following code shows the partial
declarations……..
Example…. class Encryption
{
private: void keycompare()
{
……
}
public:
…….
};
class cryptfile : public Encryption
{
……….
};
int main()
{
………..
}
Explanation….
• The function, keycompare(), is meant for
internal use by the class, Encryption.
• The derived class, cryptfile, may need to call the
function, keycompare().
• As this function is private, it is not accessible outside the class, Encryption.
• This function, however, if made public, would be
accessible throughout the program, which is
not what the designer intended.
Contd….
• The protected access specifier is used to solve the above-mentioned problem.
• A protected member of a class can be accessed by its member functions or within any class derived from it.
• Protected members behave like public members with respect to the derived class and like private members with respect to the rest of the program.
Contd…. • A class may contain all, private, protected and public access
specifiers.
• A programmer can decide……… which members require to be
declared using which access specifier, and label accordingly.
• Example: class Ex
{
private:
int a;
void fn1();
protected:
int b;
void fn2();
public:
int c;
void fn3();
};
Access Specifiers of Derivation
• class BASE
{
};
class DERIVED : _______ BASE
{
};
While inheriting, from the base class, an access
specifier should be specified, in the blank.
Contd…
• The access specifier can be private, protected or
public.
• Thus, access restrictions get imposed when
deriving the class.
Using Access Specifiers during
Derivation…
• The public Access Specifier:
In a public access specifier, all the private
members of a base class remain private in the
object, the protected members remain protected,
and the public members remain public.
Contd….
• The protected Access Specifier:
In a protected access specifier, all the private members of a base class remain private in the object, the protected members remain
protected, but all the public members of the base class become protected.
• Programmers rarely use this form of inheritance.
Contd….
• The privateAccess Specifier:
In a private access specifier, all the private members of a base class remain private in the object and all the public and protected
members in the base class become private.
• This form of inheritance depicts a composition relationship between base and the derived classes.
Illustrating 3 types of Inheritance derivations…. Note
the use of different access specifier in each derivation in
each case.
• Case I class BASE
{
private:
int a,b;
protected:
int c,d;
public:
int e;
int fn();
};
class DERIVED : public BASE
{
private:
int p,q;
protected:
int r, s;
public:
int t;
int D( );
};
• Case 2 class BASE
{
private:
int a,b;
protected:
int c,d;
public:
int e;
int fn();
};
class DERIVED: protected BASE
{
private:
int p,q;
protected:
int r, s;
public:
int t;
int D( );
};
• Case 3 class BASE
{
private:
int a,b;
protected:
int c,d;
public:
int e;
int fn();
};
class DERIVED: private BASE
{
private:
int p,q;
protected:
int r, s;
public:
int t;
int D( );
};
Shown below is the visual representation of the
objects of the DERIVED class….
• One object is shown for each case, and the access specifiers
of the members of the objects are also shown alongside.
a b p q
c d r s
e fn() t D( )
a b p q
c d e r s fn()
t D( )
a b c d p q
e fn()
r s
t D( )
Private Members
Protected Members Public Members
Case 1 Case 2 Case 3
Let’s understand…
• In the code shown previously, e is a public
member variable of the BASE class.
• As it can be seen from the visual representation of the object, the member variable, e, has public access in the object, if DERIVED has a public access specifier.
• It has a protected access in the object, if DERIVED has a protected access specifier.
• It has a private access in the object, if DERIVED has a private access specifier.
Contd…
• In the DERIVED object of the type, CASE 1 (public access specifier), the vafunction fn().riable, a could have been accessed through the
• In CASE 3, the function itself has gone into the private area of the object and thus, the variables of the BASE class can no longer be accessed.
• Thus public inheritance (through public access specifier in derivation) propagates hierarchy, while a private inheritance (through private access specifier in derivation) effectively stops a hierarchy.
The Golden rule of Access Specifiers
• ONCE PRIVATE ALWAYS PRIVATE.
• A public member can be made protected or
private, a protected member can be made private,
but ONCE PRIVATE ALWAYS PRIVATE.
• Any non-private variable or method made private
either by original declaration or private
inheritance will remain private on all further
inheritances.
Order of call of Constructors &
Destructors…
• Constructors are called in the order of BASE-to-DERIVED.
• Destructors are called in the order of DERIVED-to-BASE.
Example for order of invoking of constructors and destructors • #include< iostream.h>
#include<iomanip.h>
class BASE
{
public:
BASE()
{
cout<<“Constructor of BASE”<<endl;
}
~BASE()
{
cout<<“Destructor of BASE”<< endl;
}
};
Contd…
class DERIVED : public BASE
{
public:
DERIVED()
{
cout<<“Constructor of DERIVED”<<endl;
}
~DERIVED()
{
cout<<“Destructor of DERIVED”<<endl;
}
};
int main()
{
DERIVED obj;
return 0;
}
Output of the program is…..
• Constructor of BASE
• Constructor of DERIVED
• Destructor of DERIVED
• Destructor of BASE
Uses of Inheritance
• Extending Functionality:
It is quite possible that in a large project, several programmers share a class.
In such case, individual programmers may not be permitted to modify the class.
If a programmer wants to add certain functions or attributes to the class at this stage, he or she may create a new class that inherits all the members from the original class and then, use the derived class.
This brings about reusability, rather than recreation from scratch.
Another use of Inheritance…
• Implementation of Generalization:
Generalization is the building up of a hierarchy by
grouping the common attributes and methods of
several classes into one base class and inheriting the members in various derived classes.
B1 B2
B3 B4
B5
Derived1
Further derived classes
Types of Inheritance…
• One important object-oriented mechanism is multiple inheritance.
• Multiple inheritance means that one subclass can have more than one superclass.
• This enables the subclass to inherit properties of more than one superclass and to ``merge'' their properties.
• If class A inherits from more than one class, ie. A inherits from B1, B2, ..., Bn, it is called as multiple inheritance.
• A Familiar example of MI is children inheriting different characteristics of their parents.
Example… • #include< iostream.h>
class base1
{
protected:
int ivar1;
public:
void show1 ()
{
cout<<ivar1<<endl;
}
};
class base2
{
protected:
int ivar2;
public:
void show2()
{
cout<<ivar2<<endl; } };
Contd….
• class derived : public base1, public base2
{
public:
void set(int ix, int iy)
{
ivar1=ix;
ivar2=iy;
}
};
int main()
{
derived obj;
obj.set(10,20)
obj.show1();
obj.show2(); return 0;
}
Access Specifier in MI…
• The default access specifier is private.
• class derived : public base1, base2
{
};
This means that, base1 will have public access and base2 would have private, since it has not been mentioned.
If one intends public access, one should explicitly declare.
Ambiguity in Multiple Inheritance…
• Multiple Inheritance creates a lot of ambiguities.
• For example, what happens when two base
classes contain a function of the same
name?
• The program below illustrates this
ambiguity, as the function disp() is inherited
from both the classes, base1 and base2.
Example of Ambiguity in MI…
• #include<iostream.h>
class base1
{
public:
void disp()
{
cout<<“Base1”<<endl;
}
};
class base2
{
public:
void disp()
{
cout<<“Base2”<<endl;
}
};
Contd….
class derived : public base1, public base2
{
};
int main()
{
derived obj;
obj.disp(); //ambiguous function call
return 0;
}
Ambiguity…
• In main() function of the above program, the
reference to the function, disp() is ambiguous.
• The compiler does’nt know which function to
invoke, that of the class, base1, or the class base2,
since the derived class does not have the disp()
function.
• The ambiguity can be resolved in few ways.
• One of the way is use of scope resolution operator
while calling the function.
Rewriting the main() of the above
program to resolve ambiguity…
• int main()
{
derived obj;
obj.base1::disp(); //calling disp() of base1
obj.base2::disp(); //calling disp() of base2
return 0;
}
2nd method to resolve ambiguity… Using Overriding…….
#include<iostream.h>
class base1
{
public:
void disp()
{
cout<<“Base1”<<endl;
}
};
class base2
{
public:
void disp()
{
cout<<“Base2”<<endl;
}
};
The program… • #include<iostream.h>
class A
{
public:
int Avar;
};
class B : public A
{
public:
int Bvar;
};
class C: public A
{
public:
int Cvar;
};
Contd… class D: public B, public C
{
public :
int Dvar;
};
int main()
{
D Dtemp;
Dtemp.Avar=10; //This is ambiguous
return 0;
}
Contd…
The above program will display an error
because the reference to the variable Avar
in Dtemp is ambiguous.
This ambiguity is caused because class D
inherits one copy of Avar through class
B and another through class C
Resolving the ambiguity….
• This ambiguity can be resolved in 2 ways.
• The first method is to use the scope resolution
operator :: • Let’s modify the main() in the following manner:
• int main()
{
D Dtemp;
Dtemp.B::Avar=10; // Refers to Avar inherited from class B
Dtemp.C::Avar=20; // Refers to Avar inherited from class C
return 0;
}
The other way is to use a Virtual Base class
• The principle behind virtual base classes is to have
only one copy of the base class members in
memory.
• Inheriting a class more than once through multiple
paths creates multiple copies of the base class
members in memory.
• Thus, by declaring the base class inheritance as
virtual, only one copy of the base class is inherited.
• A base class inheritance can be specified as
virtual using the virtual qualifier.
Example……
• class A
{…….};
class B : virtual public A
{……};
class C: virtual public A
{……};
class D: virtual public C
{……};
Contd….
int main()
{
D Dtemp;
Dtemp.Avar=10; //No ambiguity because only one
return 0; // copy of Avar exists.
}
The virtual qualifier
• In the above example, the classes, B and C,
use the virtual keyword to inherit the
members of class A.
• Thus, class A is the virtual base class and
class D inherits only one copy of the
member data, Avar, from class A.
• Therefore, any reference to the member,
Avar, through an object of class C does not
lead to ambiguity.