Base class

advertisement
Unit 2
Overloading and Inheritance
Operator overloading
• C++ incorporates the option to use standard
operators to perform operations with classes
in addition to with fundamental types. For
example:
int a, b, c;
a = b + c;
• Nevertheless, it is not so obvious that we
could perform an operation similar to the
following one:
struct {
string product;
float price;
} a, b, c;
a = b + c;
Vector addition
Write a C++ program for vector
addition
Program for vector addition
Cont…
What if instead of
airPlane.addVectors(propellor,wind);
We wrote (in main)
airPlane = propellor + wind;
Compile time errors
• Multiple markers at this line
• - 'Vector' is not derived from 'const std::basic_string<_CharT,
Traits, _Alloc>'
• - mismatched types 'const _CharT*' and 'Vector'
• - candidates are:
• - no match for 'operator+' (operand types are 'Vector' and
'Vector')
• - 'Vector' is not derived from 'const
std::reverse_iterator<_Iterator>'
Need of overloading?
• The user can understand the operator
notation more easily as compared to a
function call because it is closer to the real-life
implementation.
• Associating a set of meaningful operators,
manipulation of an ADT can be done in a
conventional and simpler form.
Original meaning of operators never
get lost, when it’s overloaded
Types of operator
• Assignment(=)
• Unary (+5 or -x)
• Binary(a+b or 4-6 etc)
• Homework
Data X,Y;
– Copy the data member of object X into Y by
overloading the assignment operator(without
using copy constructor), cout<<Y.getData();
Overloading using Binary operator
• Example: Vector addition
• airPlane = propellor + wind;
//it’s like,
//airPlane = propellor.operator+(wind)
•
•
#include <iostream>
using namespace std;
•
•
•
•
class Vector {
private:
int ax;
int ay;
•
•
•
•
•
public:
Vector() {
ax = 0;
ay = 0;
}
•
•
•
•
Vector(int ax, int ay) {
this->ax = ax;
this->ay = ay;
}
•
•
int getAx() {return ax;}
int getAy() {return ay;}
•
•
•
•
void addVectors(Vector propellor, Vector wind) {
this->ax = propellor.getAx() + wind.getAx();
this->ay = propellor.getAy() + wind.getAy();
}
•
•
Vector operator+ (Vector);
};
•
•
•
•
•
•
Vector Vector::operator+ (Vector param) {
Vector temp;
temp.ax = ax + param.ax;
temp.ay = ay + param.ay;
return (temp);
}
•
•
•
int main(int argc, char **argv) {
Vector propellor(3, 4), wind(7, 5), airPlane;
cout << airPlane.getAx() << endl;
•
airPlane = propellor + wind;//it's like, propellor.operator+(wind)
•
•
•
cout << airPlane.getAx()<<endl;//prints 10
cout << airPlane.getAy(); //prints 9
}
Overloading using Unary operator
• Modification to previous program is to add
one more long data and negate it as well.
Friend classes
• We can define a class as friend of another
one, granting that first class access to the
protected and private members of the second
one.
• Example- Create a class twoInt (only only
getter setter methods should be there). Make
class Sum (friend of twoInt) with method
int
addXY(twoInt ob); and in main call this method
to print the addition of two integers(x,y)which
are present in twoInt.
• If class X is friend of class Y, it means X can
have access to members of class Y but reverse
is not true.
• E.g. class Y{
int j;
public:
friend class X; //X is friend of Y
};
• To make class Y friend of class X we have to
write
• class X{
int k;
public:
friend class Y; //Y is friend of X
};
• Another property of friendships is that they
are not transitive: The friend of a friend is not
considered to be a friend unless explicitly
specified.
Friend function
• In principle, private and protected members
of a class cannot be accessed from outside
the same class in which they are declared.
However, this rule does not affect friends.
• Create two classes alpha and beta with one
constructor and one integer in each without
any member function. In main print the
addition of those integers.
• Friend class or function declarations can be
placed anywhere in the class; it doesn’t
matter whether it goes in the public or the
private section.
Operator overloading using friends
• Friend functions can be used in the place of
member functions for overloading a binary
operator.
• Friend function requires two arguments to be
explicitly passed; while in case of member
function, it requires only one.
Example
• Create a class Person with Fname and Lname.
Create 3 objects p1,p2,p3. With the use of
friend overloading, in main call p3=p1+p2;
which should create new person p3, with
Lname of p1 and Fname of p2.
E.g. p1=“Vaibhav Lokhande”
p2=“Priyanka Chopra”
then p3=“Priyanka Lokhande”
//It means p1 and p2 got married.
Why overloading using friends???
• In some cases it’s necessary to use friend
function rather than member function.
E.g. In the previous wedding example, what if
the operator overloading is done without
using friend function???
What are the advantages and disadvantages?
• Advantage (without using friends)- Only one
parameter is required for overloading
function.
Disadvantage(without using friends)
Case-1
What if the line 61 is replaced with
p3 = “Lokhande" + p2; //got married
Case-2
What if the line 61 is replaced with
p3 = p2 + " Lokhande ";
Will program run?
• In both the cases, program will give compile
time errors.
-The left hand operand that is accountable
for invoking the member function should be
an object of the same class.
-Both the operands (on RHS) should be
object of same class.
In both the cases, one is object of
Person class and other is string type(built-indata type or primitive type).
If we want to make case-1 to run
successfully, what to do???
• Use operator overloading with friends.
Giving direct access to set private members (via
friend) makes program run faster, because setting via
setters is kind of indirection
Homework
• Write a program for case-2!!!
• What if line 70 in previous slide is changed
with
p3 = p1 + 2;
(Re-write a program to sort out the errors, so
that it will print Vaibhav 2)
Rules for operator overloading
• New operators can’t be produced, though you
are using valid operators (e.g. new+delete )
• In binary operator overloading without using
friends, left hand operand must be of userdefined type (object of class)
• 2 pgms- same functionality of two funs..one is
member n other is non-member…which one
will be called?
• Without making friend fun,…try to overload +
with non-member…try to access private
data……ask for the error.
What is the output???
• Compile time error……accessing private data
members in non-member function without
making it as friend.
What will be the error???
Multiple markers at this line - ambiguous overload for
'operator+' (operand types are 'Person' and 'Person')
Is it possible to make main a friend of
any class???
• It is possible but it will not have any effect.
• Means you will not be able to access the
private members (directly or through object of
that class).
Some rules for operator overloading
• The basic meaning of an operator can’t be
changed.
• Overloaded operators can’t be overridden.
• Member functions can be used to overload
certain operators while friend functions can’t
be.
• The left-hand operand must be an object of
relevant class, in case of binary operators
overloaded through member function.
• Overloaded operators must be a non-static
member function or a global function (should
be friend of that class). A global function must
take at least one argument that is of class or
enumerated type or that is reference to a class
or enumerated type.
• Overloaded operators (function) can’t have
default arguments.
• . .* ::
overloaded.
?;
these operators can’t be
• = ()
[]
-> these operators can’t be
used with friend keyword.
Type conversions
•
•
•
•
•
•
•
int s;
float k = 5.5;
s = k;
cout<<s; //output is 5
s= 9;
k = s;
cout<<k; //output is 9
• This is an example of automatic/implicit type
conversion, since built in data-types are used.
• Conversion from basic to Class type
• Conversion from class to basic type
• Conversion from class to class type
Conversion from basic to Class type
• Line 21 is like implicit overloading of
= operator, which in turn calls parameterized
constructor.
What will be the output???
• Compile time error at line 16Multiple markers at this line - no match for
'operator=' (operand types are 'Time‘ and 'int')
- candidate is:
If we add parameterized constructor, then
problem will be solved.
But how to solve the above problem, without
using parameterized constructor??
Overload operator =
That’s it!!!
Homework!!!
• Make operator= an friend function.
Ans- It is not possible, since friend function will
not be able to overload = operator.
Conversion from class to basic type
(Using casting operator function)
What will be the output???
• Compile time error-'int Vector::x' is private
'float Vector::y' is private
• This is another way to convert class to float
float g = float(v);
• The casting operator function must satisfy
-It should be class member
-No return type and no arguments
Conversion from class to class type
Output will be 9
15.9
• Converting Vector to Vect i.e. copying x to x1
and y to y1.
• Such a conversion from Vector to Vect class
takes place by constructor or conversion
function.
• Conversion function has prototype
operator typename() { }
where typename is user-defined type (like
class) or built-in-type (like int).
Homework!!!
• Use constructor method to convert Vector to
Vect and not conversion function.
Inheritance
• Definition- Receive/Obtain something from
someone.
• E.g. Square IS-A Polygon, Child inherits some
properties from Mom and Mom IS-A Person
therefore Child IS-A Person…..
Polygon- A plane shape with 2 dimensions viz
length and height (with straight lines).
Apart from being Polygon, square has
3 unique features
Triangle
• Square IS-A polygon as well as triangle IS-A
polygon
• Polygon is called as Base class and square and
triangle are called as Derived classes.
• Create a class Polygon with 2 attributes as
length and width with POJO. Now create a
class Rectangle as derived from Polygon.
Rectangle will have function to calculate area
of Rectangle.
Set length = 5 and width = 7 using Rectangle
object and display the area.
• Create a class Polygon with 2 attributes as
length and width with POJO. Create a class
Rectangle which extends Polygon.
Now create a class Square as derived from
Rectangle. Square will have function to
calculate area of square.
Set length = 5 and width = 7 using Square
object and display the area.
Note: Protected members are not only
accessible to immediate derived class but
to any level of derived classes.
• To define a derived class, use syntax
class derived-class: access-specifier base-class
• The access-specifier is required to give access to
the next class, who is going 2 derive form
derived class.
• There are 3 access specifiers: public, protected
and private.
• Public: When deriving a class from a public
base class, public members of the base class
become public members of the derived class
and protected members of the base class
become protected members of the derived
class.
• A base class's private members are never
accessible directly from a derived class, but
can be accessed through calls to the public
and protected members of the base class.
• Protected : When deriving from a protected
base class, public and protected members of
the base class become protected members of
the derived class.
• Private : When deriving from a private base
class, public and protected members of the
base class become private members of the
derived class.
What will be the output???
Output will be 100
• In line 11, Polygon gives protected access to
Rectangle class….it means that, Public
members of Polygon will be public to the
classes which will derive from Rectangle and
protected members of Polygon will be
protected to the classes which will derive
from Rectangle.
What will be the output???
• The code will not compile because
using namespace std; is missing.
In exam this kind of tricks examiners usually
don’t do….but it was to test the reading
power of one’s eyes….!!!
Conclusion- Apart from active listener you
should be active reader….thanks to Soft Skill…
What will be the output???
• Compile time error at line 27 and 30, since
class Rectangle gets private derived access
from Polygon.
• Due to that, protected members of Polygon
(length, height) will become private in
Rectangle.
• At line 27 and 30 in class Square, we are trying
to access these private variables, which gives
compile time error.
Access Control and Inheritance
• A derived class can access all the non-private
members of its base class.
What will be the output(WWBTO)???
Base
Derived
• Although the constructors and destructors of
the base class are not inherited themselves,
default constructor and destructor of base
class are always called when a new object of
a derived class is created or destroyed.
WWBTO???
BaseC
Derived
BaseD
WWBTO???
BaseC
Derived
Types of Inheritance
• Single- one derived class inherits from one
base classs
• Multiple- one derived class inherits from
multiple base classes
• Hierarchical- multiple subclasses inherits from
one base class
• Multilevel- here subclass acts as a base class
for other classes
• Hybrid- combination of other (previous 4)
types of inheritance
Homework- Create your own examples of any 2
types of inheritance and implement
it.
Multiple inheritance
• In C++ it is perfectly possible that a class
inherits members from more than one class.
This is done by simply separating the different
base classes with commas in the derived
class declaration.
• E.g. class CRectangle: public CPolygon, public
COutput;
• Output:
20
10
WWBTO???
Compile time error at line 27,30
• If while defining derived class, accessspecifier is not specified then by default it’s
private.
• A class can always access its own members in
spite of any access specifier.
• If the base class has no default constructor or
you want that an overloaded constructor is
called when a new derived object is created,
you can specify it in each constructor
definition of the derived class:
derived_constructor_name (parameters) :
base_constructor_name (parameters) {...}
Lets see an example….
Output
Polymorphism
• Before getting into this section, it is
recommended that you have a proper
understanding of pointers and class
inheritance.
• If any of the following statements seem
strange to you, you should review the
indicated sections:
• Polymorphism is a generic term that means
'many shapes'.
• In C++ the simplest form of Polymorphism is
overloading of functions, for instance several
functions called SortArray( arraytype ) where
sortarray might be an array of ints, or doubles.
• Typically, polymorphism occurs when there is
a hierarchy of classes and they are related by
inheritance.
• C++ polymorphism means that a call to a
member function will cause a different
function to be executed depending on the
type of object that invokes the function.
• The most common use of polymorphism in
OOP occurs when a parent class reference is
used to refer to a child class object.
• Ex- Class square and triangle are derived from
class polygon. There is function called area in
both child classes. Use set_values function in
base class to initialize values of width and
height. Use only one base class pointer to
set_values for square then display the area.
Now use same pointer to set values for
triangle and display its area as well.
Virtual members
• A member of a class that can be redefined in
its derived classes is known as a virtual
member.
• In order to declare a member of a class as
virtual, we must precede its declaration with
the keyword virtual.
Virtual Functions
• WWBTO???
• Polymorphism works on pointer of class type
and not on which derived class’s address it
holds.
• What if, we remove show function from Base
class???
WWBTO???
Compile-time error at line 33,37
• Since p is pointer to class Base, compiler will
try to search show function in Base class.
Show function is not available in Base class, so
it will give an error.
• Oh my God….how to make it work?!!!!!
– Its virtual function
• If both base and derived classes has same
function, then using pointer of base class we
can call derived class function. (make base
class function vitrual)
WWBTO???
WWBTO???
20
10
0
WWBTO if we remove keyword
virtual???
0
0
0
• That is because instead of calling the
corresponding area() function for each object
(CRectangle::area(), CTriangle::area() and
CPolygon::area(), resp), CPolygon::area() will
be called in all cases since the calls are via a
pointer whose type is CPolygon*.
Abstract base classes
• Abstract base classes are something very
similar to our CPolygon class of our previous
example.
• The only difference is that in our previous
example we have defined a valid area()
function with a minimal functionality whereas
in an abstract base classes we could leave
that area() member function without
implementation at all.
• This is done by appending =0 (equal to zero)
to the function declaration.
• This type of function (area) is called a pure
virtual function, and all classes that contain
at least one pure virtual function are abstract
base classes.
WWBTO???
Compile-time error (line 29)
• The main difference between an abstract base
class and a regular polymorphic class is that
because in abstract base classes at least one
of its members lacks implementation we
cannot create instances (objects) of it.
• But a class that cannot instantiate objects is
not totally useless. We can create pointers to
it and take advantage of all its polymorphic
abilities.
• CPolygon includes a pure virtual function and
therefore it's an abstract base class. However,
pointers to this abstract base class can be
used to point to objects of derived classes.
• Pure virtual members can be called from the
abstract base class.
WWBTO???
20
10
Homework!!!
• What happens if we change line 29 to 32 by
following two lines…..
CPolygon * ppoly1 = new CRectangle;
CPolygon * ppoly2 = new CTriangle;
Will number of lines of code increase or
decrease???
More @ virtual
• By default, C++ matches a function call with
the correct function definition at compile
time. This is called static binding.
• You can specify that the compiler match a
function call with the correct function
definition at run time; this is called dynamic
binding.
• You declare a function with the keyword
virtual if you want the compiler to use
dynamic binding for that specific function.
• Homework- Distinguish between pointers and
references in C++
static binding
Output is Class A
Why???
• At compile time, the compiler knows only that
the argument of function g() will be a
reference to an object derived from A,
therefore function A::f() is called.
How to print Class B as output???
• The virtual keyword indicates to the compiler
that it should choose the appropriate
definition of f() not by the type of reference,
but by the type of object that the reference
refers to.
• A class that declares or inherits a virtual
function is called a polymorphic class.
WWBTO???
• Compile-time error at line 20 because trying
to invoke parameterized function f which is
not available.
WWBTO???
Class A
Class C
Though at line 20 pa1 contains address of class
B, class B don’t have function with prototype
f(). Therefore it takes it from base class itself.
Covariant
• Ex- Class Derived inherits from class Base.
Base class contains pure virtual function called
clone(). Clone function’s work is to create
object of the class dynamically where it’s
defined. First create Derived class’s one object
dynamically, like Derived* d = new Derived;
Now using d create one clone and point
d2( derived class pointer) to it.
WWBTO???
Compile-time error at line 41
• invalid conversion from 'Base*' to 'Derived*‘
• Line 35 is equal to (Base *)new Derived;
We are assigning Base pointer to Derived
pointer, which is not possible.
Then how to remove the error???
WWBTO???
• If, instead, the clone() method could tell the
compiler "actually, I always return a Derived*"
(i.e.
it
became
virtual
Derived*
Derived::clone() we could do away with the
upcast and the check, moving all this away
from run-time and into compile-time:
Derived* d = new Derived;
Derived* d2 = d->clone();
This is the ideal solution; there is no run-time
cost associated with it, and it's completely
safe (homework—what is run-time cost,
safety).
Derived * clone() is covariant function,
output is B_Clone
• The return type of an overriding function must
be identical to the function that it is
overriding.
• The C++ Standard allows one specific
exception to this rule that could possibly come
in handy to save some unnecessary casting.
• In an overridden method that returns a
pointer or a reference to a class, you are
allowed to change the return type to a derived
class instead.
• What is covariant???
• Changing (variable) in such a way that
interrelations with other variable remain
unchanged.
• Means, even if someone is changing….they
are still compatible to each other.
Covariant return type
• In object-oriented programming, a covariant
return type of a function is one that can be
replaced/changed by a "narrower" type when
the function is overridden in a subclass.
• Derived class return type is said to be
covariant.
Constructor, Destructor and virtual
destructor
• WWBTO???
• Compile time error since constructors are
private.
WWBTO???
a
b
WWBTO???
a
b
~a
Destructor of class B is not called because of
static binding.
How to call it?
Virtual destructor
a
b
~b
~a
Note: While dealing with inheritance make
destructors virtual.
Binding
• Conversion of variables or function names
into machine language addresses.
• Early/static binding- A direct call to function is
considered as early binding.
At compile time, compiler is able to find
address of function or variable.
Example
Late/dyanmic binding
• In some cases, we come to know which
function to call at runtime, it’s late binding.
• Early binding is fast, efficient and less
complex.
• Late binding is slow, complex but more flexible
compared to early binding.
Container classes
• A container is a holder object that stores a
collection of other objects (its elements).
• They are implemented as class templates,
which allows a great flexibility in the types
supported as elements.
• The container manages the storage space for
its elements and provides member functions
to access them, either directly or through
iterators.
• E.g. dynamic arrays (vector), queues (queue),
stacks (stack), heaps (priority_queue), linked
lists (list), trees (set), associative arrays
(map)...
To know more….
• http://www.google.co.in/url?sa=t&rct=j&q=&
esrc=s&source=web&cd=3&cad=rja&ved=0CD
0QFjAC&url=http%3A%2F%2Fwww.cs.colorad
o.edu%2F~main%2Fsupplements%2Fchapt03.
ppt&ei=1-vdUradM4IrAff9IDICQ&usg=AFQjCNFltjHNKDvbOIsoKE7l
Oj0YDX_Jeg&sig2=qPSy4ak5BczeIW87qoRcVA
Static class
• Class that only has static members
Ambiguity in multiple inheritance
• The ambiguity simply means the state when
the compiler confused.
• So call to ambiguous members will result in
compile-time error.
• http://publib.boulder.ibm.com/infocenter/lnx
pcomp/v8v101/index.jsp?topic=%2Fcom.ibm.
xlcpp8l.doc%2Flanguage%2Fref%2Fcplr138.ht
m
• In multiple inheritance, there may be
possibility that a class may inherit member
functions with same name from two or more
base classes and the derived class may not
have functions with same name as those of its
base classes. If the object of the derived class
need to access one of the same named
member function of the base classes then it
result in ambiguity as it is not clear to the
compiler which base’s class member function
should be invoked.
Lets code this scenario……
WWBTO???
Solution of ambiguity in multiple
inheritance
• The output to last program is a_abc
• The ambiguity can be resolved by using the
scope resolution operator to specify the class
in which the member function lies.
Virtual base classes
• Virtual base classes offer a way to save space
and avoid ambiguities in class hierarchies that
use multiple inheritance.
• The following figure shows the conceptual
memory layout.
• Note that there are two Queue subobjects in
the LunchCashierQueue object.
• Declare Queue a virtual base class will
ensures that only one copy of the subobject
Queue is included
WWBTO???
Compile time error
Multiple markers at this line
- no matching function for
'PoweredDevice::PoweredDevice()‘
call
to
When we called parameterized constructor, in
derived class, we are not mentioning which base
class constructor to be called. So by default, it will
call default constructor…which is not present in
base class…..so it will give an error.
• Check slide # 115-117
Correction to last program
“diamond problem” in multiple inheritance
• If you were to create a Copier class object, by
default you would end up with two copies of
the PoweredDevice class — one from Printer,
and one from Scanner.
WWBTO???
• How not to print PoweredDevice: 3 twice???
• How to bring the following output???
While deriving base class, make it
virtual to immediate derived classes
• To share a base class, simply insert the
“virtual” keyword in the inheritance list of the
derived class. This creates what is called a
virtual base class, which means there is only
one base object that is shared.
• Here is the an example (without constructors for
simplicity) showing how to use to virtual keyword to
create a shared base class:
• Now, when you create a Copier class, you will get
only one copy of PoweredDevice that will be shared
by both Scanner and Printer.
• Who is responsible for creating PoweredDevice
object?
– The Copier constructor is responsible for creating
PoweredDevice. Consequently, this is one time
when Copier is allowed to call a non-immediateparent constructor directly.
• If a class inherits one or more classes that have
virtual parents, the most derived class is
responsible for constructing the virtual base
class.
• Note that this is true even in a single
inheritance case: if Copier was singly inherited
from Printer, and Printer was virtually
inherited from PoweredDevice, Copier is still
responsible for creating PoweredDevice.
Download