computer science department inheritance & polymorphism
of 44
/44
Computer Science Department Inheritance & Polymorphism
Embed Size (px)
DESCRIPTION
Computer Science Department Polymorphism A function/operator can behave differently depending on the context in which it is called We have already seen operator overloading in which a single ‘+’ operator behaves differently when used with floats, ints or strings Polymorphism refers to the ability of similar objects to respond differently to the same message i.e., the same type of function call Selecting the correct function is deferred until runtime and is based on the object CPS235:Polymorphism3TRANSCRIPT
Slide 1Inheritance
Polymorphism
CPS235:Polymorphism
Polymorphism
A function/operator can behave differently depending on the context in which it is called
We have already seen operator overloading in which a single ‘+’ operator behaves differently when used with floats, ints or strings
Polymorphism refers to the ability of similar objects to respond differently to the same message i.e., the same type of function call
Selecting the correct function is deferred until runtime and is based on the object
CPS235:Polymorphism
The new class is a type of the existing class
enum note { middleC, Csharp, Cflat };
class Instrument {
class Wind : public Instrument {};
Upcasting (contd..)
A Wind object is also an Instrument object, and there’s no function that tune( ) could call for an Instrument that isn’t also in Wind
Inside tune( ), the code works for Instrument and anything derived from Instrument, and the act of converting a Wind object, reference, or pointer into an Instrument object, reference, or pointer is called upcasting
CPS235:Polymorphism
Instrument* ip = &w; // Upcast
Instrument& ir = w; // Upcast
Of course, any upcast loses type information about an object. If you say
Wind w;
Instrument* ip = &w;
the compiler can deal with ip only as an Instrument pointer and nothing else i.e., it cannot know that ip actually points to a Wind object
So when you call the play( ) member function by saying
ip->play(middleC);
the compiler can know only that it’s calling play( ) for an Instrument pointer, and call the base-class version of Instrument::play( ) instead of what it should do, which is call Wind::play( )
CPS235:Polymorphism
class Instrument {
Instrument::play
This is clearly not the desired output, because you know that the object is actually a Wind and not just an Instrument
The call should resolve to Wind::play
The above discussion also applies if you use a pointer to an Instrument in the function tune
CPS235:Polymorphism
Computer Science Department
Function call binding
Connecting a function call to a function body is called binding
When binding is performed before the program is run (by the compiler and linker), it’s called early binding or static binding
The problem in the above program is caused by early binding because the compiler cannot know the correct function to call when it has only an Instrument address
CPS235:Polymorphism
Dynamic Binding
The solution to the above problem is called late binding or dynamic binding which means the binding occurs at runtime, based on the type of the object
When a language implements late binding, there must be some mechanism to determine the type of the object at runtime and call the appropriate member function
The compiler still doesn’t know the actual object type, but it inserts code that finds out and calls the correct function body
Implemented in C++ using virtual functions
CPS235:Polymorphism
Virtual Functions enable run time object determination
Keyword virtual instructs the compiler to use late binding and delay the object interpretation
How ?
Define a virtual function in the base class. The word virtual appears only in the base class
If a base class declares a virtual function, it must implement that function, even if the body is empty
Virtual function in base class stays virtual in all the derived classes
It can be overridden in the derived classes
But, a derived class is not required to re-implement a virtual function. If it does not, the base class version is used
CPS235:Polymorphism
class Instrument {
Extensibility
With play( ) defined as virtual in the base class, you can add as many new types as you want to the system without changing the tune( ) function
Such a program is extensible because you can add new functionality by inheriting new data types from the common base class
The functions that manipulate the base-class interface will not need to be changed at all to accommodate the new classes
CPS235:Polymorphism
class Instrument {
void adjust(int) {}
void adjust(int) {}
void adjust(int) {}
};
};
class Base {
void g()const { cout<<“Base”; }
void g() { cout<<“derived”; }
void main() {
Derived d;
cout << "b2.f() = " << b2.f() << endl;
cout<<“b1->show()=”; b1->show();
}
class Base {
};
int sum() const { return Base::sum() + j; }};
void call(Base b) {
*
If you use an object instead of a pointer or reference as the recipient of your upcast, the object is “sliced”
CPS235:Polymorphism
Polymorphism Summary
When you use virtual functions, compiler stores additional information about the types of object available and created
Polymorphism is supported at this additional overhead
Important :
Not with objects even if the function is virtual
CPS235:Polymorphism
Some classes exist logically but not physically.
Example : Shape
Shape s; // Legal but silly..!! : “Shapeless shape”
Shape makes sense only as a base of some classes derived from it. Serves as a “category”
Hence instantiation of such a class must be prevented
class Shape //Abstract
functions is an Abstract Class
Objects of abstract class can’t be
created
CPS235:Polymorphism
*
A pure virtual function not defined in the derived class remains a pure virtual function.
Hence derived class also becomes abstract
class Circle : public Shape { //No draw() - Abstract
public :
}
Abstract Classes & Pure Virtual Functions
CPS235:Polymorphism
Abstract classes
If a method is to be over-ridden by each child class, we can enforce this policy through the use of abstract classes
You can’t create an object of an abstract class ( a class with at least one pure virtual function)
You can also not pass or return an object of an abstract class by value
CPS235:Polymorphism
Abstract classes
It is still possible to provide definition of a pure virtual function in the base class
The class still remains abstract and functions must be redefined in the derived classes, but a common piece of code can be kept there to facilitate reuse
class Shape { //Abstract
Virtual Destructor
If any of the functions in your class are virtual, the destructor should be virtual as well
class Base {
}
Computer Science Department
Things to remember
Beginning a class method declaration with the keyword virtual in a base class makes the function virtual for the base class and all derived classes, classes further derived from derived classes, and so on…
dynamic binding is possible only for a base class pointer or reference to an object of the derived class
All those functions of the base class that need to be over-ridden in the derived classes should be made virtual
Constructors cannot be virtual
Destructors can be virtual
You should provide a base class which has virtual functions with a virtual destructor even if the class does not need a destructor (i.e., it does not contain dynamic data)
CPS235:Polymorphism
Computer Science Department
Things to remember
friends can’t be virtual since they are not member functions
If a derived class does not redefine a virtual function, the base class version is used. If there is a chain of derived classes, then the most recently defined version of the virtual function is used
An abstract class demands that its pure virtual functions must be over-ridden in each derived class, otherwise the derived class also becomes abstract
CPS235:Polymorphism
Inheritance and Dynamic Memory Allocation
If a base class uses dynamic memory allocation and redefines assignment operator and copy constructor, how does it affect the implementation of the derived class?
If the derived class does not itself use dynamic memory allocation, no special steps need to be taken
If the derived class uses dynamic memory allocation, then the assignment operator and copy constructor need to be defined for the derived class as well
CPS235:Polymorphism
class base
base(const base& rs);
};
If the derived class does not use new
There’s no need for defining a destructor. The default destructor will automatically call the base class destructor which will free the memory allocated in the base part of the object
There’s no need for defining a copy constructor since the default copy constructor will automatically call the base class copy constructor for copying the base part of the object
Assignment operator overloading is also not required for the same reason
CPS235:Polymorphism
class hasDMA : public base
public:
...
};
For this class, you will have to define destructor, copy constructor and assignment operator
CPS235:Polymorphism
Destructor
Copy Constructor
strcpy(label,rs.label);
strcpy(style,hs.style);
Assignment Operator
{
strcpy(label,rs.label);
{
strcpy(style,hs.style);
stream operators
{
{
os << (const base& )rs; //type casting //lacksDMA parameter to base argument
os << "Color: " <<rs.color << endl;
stream operators
{
os << (const base& )rs; //type casting //hasDMA parameter to base argument
os << "Style: " <<rs.style << endl;
CPS235:Polymorphism
CPS235:Polymorphism
VPTR embedded in every polymorphic object
Indirect function access
Polymorphism
CPS235:Polymorphism
Polymorphism
A function/operator can behave differently depending on the context in which it is called
We have already seen operator overloading in which a single ‘+’ operator behaves differently when used with floats, ints or strings
Polymorphism refers to the ability of similar objects to respond differently to the same message i.e., the same type of function call
Selecting the correct function is deferred until runtime and is based on the object
CPS235:Polymorphism
The new class is a type of the existing class
enum note { middleC, Csharp, Cflat };
class Instrument {
class Wind : public Instrument {};
Upcasting (contd..)
A Wind object is also an Instrument object, and there’s no function that tune( ) could call for an Instrument that isn’t also in Wind
Inside tune( ), the code works for Instrument and anything derived from Instrument, and the act of converting a Wind object, reference, or pointer into an Instrument object, reference, or pointer is called upcasting
CPS235:Polymorphism
Instrument* ip = &w; // Upcast
Instrument& ir = w; // Upcast
Of course, any upcast loses type information about an object. If you say
Wind w;
Instrument* ip = &w;
the compiler can deal with ip only as an Instrument pointer and nothing else i.e., it cannot know that ip actually points to a Wind object
So when you call the play( ) member function by saying
ip->play(middleC);
the compiler can know only that it’s calling play( ) for an Instrument pointer, and call the base-class version of Instrument::play( ) instead of what it should do, which is call Wind::play( )
CPS235:Polymorphism
class Instrument {
Instrument::play
This is clearly not the desired output, because you know that the object is actually a Wind and not just an Instrument
The call should resolve to Wind::play
The above discussion also applies if you use a pointer to an Instrument in the function tune
CPS235:Polymorphism
Computer Science Department
Function call binding
Connecting a function call to a function body is called binding
When binding is performed before the program is run (by the compiler and linker), it’s called early binding or static binding
The problem in the above program is caused by early binding because the compiler cannot know the correct function to call when it has only an Instrument address
CPS235:Polymorphism
Dynamic Binding
The solution to the above problem is called late binding or dynamic binding which means the binding occurs at runtime, based on the type of the object
When a language implements late binding, there must be some mechanism to determine the type of the object at runtime and call the appropriate member function
The compiler still doesn’t know the actual object type, but it inserts code that finds out and calls the correct function body
Implemented in C++ using virtual functions
CPS235:Polymorphism
Virtual Functions enable run time object determination
Keyword virtual instructs the compiler to use late binding and delay the object interpretation
How ?
Define a virtual function in the base class. The word virtual appears only in the base class
If a base class declares a virtual function, it must implement that function, even if the body is empty
Virtual function in base class stays virtual in all the derived classes
It can be overridden in the derived classes
But, a derived class is not required to re-implement a virtual function. If it does not, the base class version is used
CPS235:Polymorphism
class Instrument {
Extensibility
With play( ) defined as virtual in the base class, you can add as many new types as you want to the system without changing the tune( ) function
Such a program is extensible because you can add new functionality by inheriting new data types from the common base class
The functions that manipulate the base-class interface will not need to be changed at all to accommodate the new classes
CPS235:Polymorphism
class Instrument {
void adjust(int) {}
void adjust(int) {}
void adjust(int) {}
};
};
class Base {
void g()const { cout<<“Base”; }
void g() { cout<<“derived”; }
void main() {
Derived d;
cout << "b2.f() = " << b2.f() << endl;
cout<<“b1->show()=”; b1->show();
}
class Base {
};
int sum() const { return Base::sum() + j; }};
void call(Base b) {
*
If you use an object instead of a pointer or reference as the recipient of your upcast, the object is “sliced”
CPS235:Polymorphism
Polymorphism Summary
When you use virtual functions, compiler stores additional information about the types of object available and created
Polymorphism is supported at this additional overhead
Important :
Not with objects even if the function is virtual
CPS235:Polymorphism
Some classes exist logically but not physically.
Example : Shape
Shape s; // Legal but silly..!! : “Shapeless shape”
Shape makes sense only as a base of some classes derived from it. Serves as a “category”
Hence instantiation of such a class must be prevented
class Shape //Abstract
functions is an Abstract Class
Objects of abstract class can’t be
created
CPS235:Polymorphism
*
A pure virtual function not defined in the derived class remains a pure virtual function.
Hence derived class also becomes abstract
class Circle : public Shape { //No draw() - Abstract
public :
}
Abstract Classes & Pure Virtual Functions
CPS235:Polymorphism
Abstract classes
If a method is to be over-ridden by each child class, we can enforce this policy through the use of abstract classes
You can’t create an object of an abstract class ( a class with at least one pure virtual function)
You can also not pass or return an object of an abstract class by value
CPS235:Polymorphism
Abstract classes
It is still possible to provide definition of a pure virtual function in the base class
The class still remains abstract and functions must be redefined in the derived classes, but a common piece of code can be kept there to facilitate reuse
class Shape { //Abstract
Virtual Destructor
If any of the functions in your class are virtual, the destructor should be virtual as well
class Base {
}
Computer Science Department
Things to remember
Beginning a class method declaration with the keyword virtual in a base class makes the function virtual for the base class and all derived classes, classes further derived from derived classes, and so on…
dynamic binding is possible only for a base class pointer or reference to an object of the derived class
All those functions of the base class that need to be over-ridden in the derived classes should be made virtual
Constructors cannot be virtual
Destructors can be virtual
You should provide a base class which has virtual functions with a virtual destructor even if the class does not need a destructor (i.e., it does not contain dynamic data)
CPS235:Polymorphism
Computer Science Department
Things to remember
friends can’t be virtual since they are not member functions
If a derived class does not redefine a virtual function, the base class version is used. If there is a chain of derived classes, then the most recently defined version of the virtual function is used
An abstract class demands that its pure virtual functions must be over-ridden in each derived class, otherwise the derived class also becomes abstract
CPS235:Polymorphism
Inheritance and Dynamic Memory Allocation
If a base class uses dynamic memory allocation and redefines assignment operator and copy constructor, how does it affect the implementation of the derived class?
If the derived class does not itself use dynamic memory allocation, no special steps need to be taken
If the derived class uses dynamic memory allocation, then the assignment operator and copy constructor need to be defined for the derived class as well
CPS235:Polymorphism
class base
base(const base& rs);
};
If the derived class does not use new
There’s no need for defining a destructor. The default destructor will automatically call the base class destructor which will free the memory allocated in the base part of the object
There’s no need for defining a copy constructor since the default copy constructor will automatically call the base class copy constructor for copying the base part of the object
Assignment operator overloading is also not required for the same reason
CPS235:Polymorphism
class hasDMA : public base
public:
...
};
For this class, you will have to define destructor, copy constructor and assignment operator
CPS235:Polymorphism
Destructor
Copy Constructor
strcpy(label,rs.label);
strcpy(style,hs.style);
Assignment Operator
{
strcpy(label,rs.label);
{
strcpy(style,hs.style);
stream operators
{
{
os << (const base& )rs; //type casting //lacksDMA parameter to base argument
os << "Color: " <<rs.color << endl;
stream operators
{
os << (const base& )rs; //type casting //hasDMA parameter to base argument
os << "Style: " <<rs.style << endl;
CPS235:Polymorphism
CPS235:Polymorphism
VPTR embedded in every polymorphic object
Indirect function access