Você está na página 1de 48

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.

Access Specifiers.revisited
The access specifiers of a class are:
private
protected
public

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 SpecifierPutting


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


deriving the class.

get

imposed

when

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

Case 2

Case 3

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( );
};

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( );
};

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.
Case 1

Case 2

Case 3

Private Members

a
c

b p
d

q
s

e fn() t D( )

Public Members

b p

a b c d p
e fn()

c d e r s fn()
t D( )

Protected Members

r
t D( )

Lets 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.

Syntax of MI
class A: public base1, public base2
{
//body of class
};

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 doesnt 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;
return 0;
}

//This is ambiguous

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

::

Lets 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;
return 0;

//No ambiguity because only one

// 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.

Você também pode gostar