Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
3 views31 pages

Lecture 3 Polymorphism

Uploaded by

2305156
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views31 pages

Lecture 3 Polymorphism

Uploaded by

2305156
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

Lecture Three

Polymorphism

© Dr. Mohammad Mahfuzul Islam, PEng


Professor, Dept. of CSE, BUET
Polymorphism

Poly = many
Morphism = shape, form or structure

Polymorphism

Function / Method Function/ Method Operator


Overloading Overriding Overloading

Constructor Destructor X
overloading Why?

2
Constructor Overloading in C++
Example for supporting array
#include <iostream> OUTPUT:
using namespace std; 01
➢It is common to overload a class’s constructor function. 02
class myclass { 03
➢It is not possible to overload a destructor function. int x; 04
public:
➢Three main reasons to overload constructor function: myclass() { x = 0;}
05

- to gain flexibility (discussed in Lecture 1) myclass(int n) { x = n;}


int getx() {return x;}
- to support arrays and };

- to create copy constructors (discussed in Lecture 2) int main() {


myclass o1[5];
➢If a program attempts to create an object for which no myclass o2[5] = {1, 2, 3, 4, 5};
matching constructor is found, a compile-time error for(int i = 0; i < 5; i++){
occurs. cout << o1[i].getx() << " ";
cout << o2[i].getx() << endl;
}
return 0;
}
3
Constructor Overloading in Java
class MyClass{ C++
private int x; myclass o2[5] = {1, 2, 3, 4, 5};

MyClass(){ x = 0;}
MyClass(int n){ x = n;} [0] [1] [2] [3] [4]
public int getX(){ return x;}
} 1 2 3 4 5

public class Main {


o2
Array of Object
public static void main(String[] args) {
MyClass[] ob = new MyClass[5];

for(int i = 0; i <ob.length; ++i){


Array of Object Java
if (i % 2 != 0)
ob[i] = new MyClass(); Why?
else ob[i] = new MyClass(i+1); [0] [1] [2] [3] [4]
}

for(int i = 0; i < ob.length; ++i){


System.out.print(ob[i].getX()+" "); ob Array of Object Reference
}
}
} OUTPUT: x ------------------
1 0 3 0 5
4
Copy Constructor
#include <iostream> void show(strtype x){
#include <cstring> char *s;
#include <cstdlib>
using namespace std; s = x.get();
cout << s << endl;
class strtype{ }
char *p; int main(){
public: strtype a("Hello"), b("There");
strtype(const char *s){
int l; show(a);
l = strlen(s) + 1; show(b);
p = new char[l]; return 0;
if (!p){ }
cout << "Allocation error\n";
exit(1);
OUTPUT:
Hello
}
There
strcpy( p, s );
CopyConstructor2(1240,0x10d697600) malloc: *** error for object
}
0x7f8d22f05a00: pointer being freed was not allocated
~strtype() { delete [] p;}
CopyConstructor2(1240,0x10d697600) malloc: *** set a breakpoint in
char *get() { return p; }
malloc_error_break to debug
};
zsh: abort ./"CopyConstructor2" 5
Copy Constructor
➢The copy constructor is invoked when a function generates the temporary object.
#include <iostream> strtype::strtype(const strtype &s){
#include <cstring> int l;
#include <cstdlib> l = strlen(s.p) + 1;
using namespace std; p = new char[l];
strcpy( p, s.p );
class strtype{ cout << "Constructing copy\n";
char *p; }
public: OUTPUT:
strtype(const char *s){ void show(strtype x){ Constructing normally
int l; char *s; Constructing normally
l = strlen(s) + 1; s = x.get(); Constructing copy
p = new char[l]; cout << s << endl; Hello
strcpy( p, s ); } Constructing copy
cout << "Constructing normally\n"; There
} int main(){
strtype(const strtype &s); strtype a("Hello"), b("There");
~strtype() { delete [] p;} show(a);
char *get() { return p; } show(b);
}; return 0;
}
6
Default Argument

➢The defaults can be specified either in function prototype or in its definition.


➢The defaults cannot be specified in both the prototype and the definition.
➢All default parameters must be to the right of any parameters that do not have defaults.

#include <iostream> #include <iostream>


using namespace std; using namespace std;

void f(int a = 0, int b = 0){ void f(int a = 0, int b);


cout << a << " " << b << endl;
} int main(){
f(10);
OUTPUT:
int main(){ f(10, 99);
0 0
f(); 10 0 }
f(10); void f(int a, int b){
10 99
f(10, 99); cout << a << " " << b << endl;
} }

7
Default Argument
➢Default argument can be used instead of function overload
#include <iostream>
#include <iostream> using namespace std;
OUTPUT:
10
using namespace std;
class myclass { 0
double rect_area( double length, double width = 0){ int x;
public:
if (!width) width = length;
myclass(int n = 0) { x = n; }
return length*width; int getx() { return x; }
} };

int main(){ OUTPUT: int main(){


cout << rect_area(10.0, 5.8) << endl; 58 myclass o1(10);
cout << rect_area(10.0) << endl; 100 myclass o2;
cout << o1.getx() << endl;
return 0;
cout << o2.getx() << endl;
} return 0;
}
➢Copy constructors may take additional arguments, as long
as the additional arguments have default values.
myclass( const myclass &obj, int x = 0){
//body of constructor
}
8
Ambiguity with Function Overloading
➢Automatic type conversion rule cause an ambiguous situation.
#include <iostream> int main(){
using namespace std; float x = 10.09;
double y = 10.09;
float f(float i){ OUTPUT: Theoretically, Java
return i / 2.0; cout << f(x) << endl;
} cout << f(y) << endl;
error: call to 'f' is ambiguous should have both Type
cout << f(10) << endl; ambiguities. But
cout << f(10) << endl;
double f(double i){
return i / 3.0;
intelligent platform like
return 0;
} } Intellij resolves such
ambiguities based on-
➢Wrong type of arguments causes an ambiguous situation. • Close proximity
#include <iostream> int main(){ • Specialization
using namespace std; f('c’);
f(86);
void f(unsigned char c){ return 0;
cout << c; }
}
OUTPUT:
void f(char c){
error: call to 'f' is ambiguous
cout << c;
}
f(86);
9
Ambiguity with Function Overloading
➢ Call by value and call by reference cause an ambiguous situation.
#include <iostream>
using namespace std; int main(){
int x = 1, y = 2;
int f(int a, int b){
return a+b; cout << f(x, y); // which f() is called?
} return 0;
}
int f(int a, int &b){
return a-b; Java doesn’t
}
have these two
➢Default argument causes an ambiguous situation. ambiguities.
#include <iostream>
using namespace std; int main(){
cout << f(10, 2);
int f(int a){ cout << f(10); // which f() is called?
return a*a; return 0;
} }
int f(int a, int b = 0){
return a*b;
}
10
Finding address of an Overloaded Function
➢A function address is obtained by putting its name on the right side of an
assignment statement without any parenthesis or arguments.
To assign p the address of zap(),
p = zap;
➢What about overloaded function???? Java
int main(){ ➢ Java doesn’t provide address level
void (*fp1)(int);
#include <iostream> void (*fp2)(int, char); access of any code due to security
using namespace std; reason.
fp1 = space; ➢ Hash Code of an object can be
void space(int count){ fp2 = space;
for( ; count; count--) cout << '_';
found using object.hashCode()
} fp1(10); method.
cout << endl;
void space(int count, char ch){ fp2(10, 'x’); A hash value is a numeric value of a
for( ; count; count--) cout << ch; cout << endl;
} fixed length that uniquely identifies
return 0; data. Mainly used for digital
OUTPUT: } signature.
__________
xxxxxxxxxx
11
Method Overriding
#include <iostream>
Using namespace std; int main() {
Rectangle r(4,5);
class Figure { Triangle t(4, 3);
double dim1, dim2; Figure *figref;
Figure(double a, double b){ dim1 = a; dim2 = b;}
virtual double area() = 0; // Pure virtual function figref = r;
virtual void show(){ cout << "Abstract";} figref.show();
} figref = t;
figref.show();
class Rectangle: public Figure {

C++ Code
Rectangle(double a, double b) { super(a, b);} return 0;
double area(){ return dim1*dim2;} }
void show(){cout << "Rectangle Area: ” << area();}
}

class Triangle: public Figure {


Triangle(double a, double b) {super(a, b);}
double area(){ return 0.5*dim1*dim2;}
OUTPUT:
Rectangle Area: 20.0
void show(){cout << ”\nTriangle Area: ” << area());
} Triangle Area: 6.0
}
Method Overriding
abstract class Figure {
double dim1, dim2;
Figure(double a, double b){ dim1 = a; dim2 = b;}
abstract double area();
void show(){ public class Main {
System.out.println("Abstract"); public static void main(String[] args) {
Rectangle r = new Rectangle(4,5);

Java Code
}
} Triangle t = new Triangle(4, 3);
Figure figref;
class Rectangle extends Figure {
Rectangle(double a, double b) { super(a, b);} figref = r;
double area(){ return dim1*dim2;} figref.show();
void show(){ figref = t;
System.out.println("Rectangle Area: "+area()); figref.show();
} }
} }

class Triangle extends Figure {


Triangle(double a, double b) {super(a, b);}
double area(){ return 0.5*dim1*dim2;}
OUTPUT:
Rectangle Area: 20.0
void show(){
Triangle Area: 6.0
System.out.println("Triangle Area: "+area());
}
}
Operator Overloading in C++
➢ When an operator is overloaded, that operator loses none of its original meaning; instead, it gains
additional meaning relative to the class.
➢ Operator can be overloaded by creating either a member operator function or a friend operator function.
➢ The general form of member operator function:
return-type class-name::operator#(arg-list){
// operation to be performed
}
➢ Two important restrictions of operator overloading:
(1) the precedence of the operator cannot be changed;
(2) the number of operands that an operator takes cannot be altered.
➢ Most C++ operators can be overloaded. Only the following operators cannot be overloaded-
(1) Preprocessor operator (2) . (3) :: (4) .* (5) ?

➢ Except for the =, operator functions are inherited by any derived class.

14
Unary Operator Overloading in C++
When Object Not Changed:
Unary Operator
No Change of Object (-ob)
Object not changed Coord Coord:: operator +(){
e.g., -c
Object changed Coord temp;
temp.x = -x; Member of
temp.y = -y; Object
Prefix Postfix return temp;
e.g., ++a, --b e.g., a++, b-- }

Prefix and Postfix Unary operations: When Object Changed:


Object before operator (ob++) No object before operator (++ob) Prefix Unary Operation:
Coord Coord:: operator ++(int notused){ Coord Coord:: operator ++(){
++a; --b; -c
x++; ++x;
Member of Postfix Unary Operation:
y++; ++y; Member of
return *this;
Object return *this; Object a++; b--
} }
To make differences, Postfix Unary
operation is assumed as
Only (int) can be used instead of (int notused). “notused” passed 0. a ++ (notused)
15
Binary Operator Overloading in C++
Binary Operator

Object changed Object not changed Binary operation when object


e.g., a = b, a += b changed:
Object before operator (ob1 += ob2)
Object before operator No object before operator Coord Coord:: operator += (Coord ob){
e.g., ob1 + ob2, ob + 100 e.g., 100 + ob, 100 == ob x += ob.x;
y += ob.y; Member of
return *this; Object
Binary operation without changing object: }

Object before operator (ob1*ob2) No object before operator (100+ob)


Coord Coord:: operator * (Coord ob){ Coord operator + (int x, Coord ob){
Coord temp; Coord temp;
temp.x = x * ob.x; temp.x = x + ob.x; Friend
temp.y = y * ob.y; Member of temp.y = x + ob.y; Function
return temp; Object return temp; Must
} }
16
Operator Overloading in C++
Coord Coord:: operator + (Coord ob){
Coord temp;
#include <iostream> temp.x = x + ob.x;
using namespace std; temp.y = y + ob.y;
return temp; ➢For Unary operator
class Coord{ }
int x, y;
overloading, the operand is
public: Coord Coord:: operator + (int i){ passed implicitly to the
Coord(int a=0, int b=0){ x = a; y = b;} Coord temp; function (identified by *this
void getxy(int &i, int &j){ i = x; j = y;} temp.x = x + i; object).
temp.y = y + i;
Coord operator + (Coord ob); return temp; ➢ When a binary operator is
Coord operator + (int i); }
Coord operator++(int); // Postfix increment overloaded, the left operand
Coord operator++(); // Prefix increment Coord Coord:: operator ++(int notused){ is passed implicitly to the
Coord operator * (Coord ob); x++; function (identified by *this
Coord operator = (Coord ob); y++;
return *this;
object) and the right
friend bool operator ==(int x, Coord ob); } operand is passed as an
friend Coord operator + (int x, Coord ob); argument.
}; Coord Coord:: operator ++(){
++x;
++y;
return *this;
}
17
Operator Overloading in C++
Coord Coord:: operator * (Coord ob){ int main(){ (20+a).getxy(x, y);
Coord temp; Coord a(10, 20), b(4, 4), c; cout << x << " " << y << endl;
temp.x = x * ob.x; int x, y;
temp.y = y * ob.y; (a + b + c + 100).getxy(x, y);
return temp; c = a++; cout << x << " " << y << endl;
} c.getxy(x, y);
cout << x << " " << y << endl; c = a++;
bool operator ==(int x, Coord ob){ a.getxy(x, y); c.getxy(x, y);
return (x == ob.x && x == ob.y); cout << x << " " << y << endl; cout << x << " " << y << endl;
}
c = ++a; return 0;
Coord operator + (int x, Coord ob) { c.getxy(x, y); }
Coord temp; cout << x << " " << y << endl;
temp.x = x + ob.x; a.getxy(x, y); OUTPUT:
temp.y = x + ob.y; cout << x << " " << y << endl; 110 120
return temp;
11 21
} (a*b).getxy(x, y); 112 122
cout << x << " " << y << endl;
12 22
Coord Coord:: operator = (Coord ob){
48 88
x = ob.x + 100; // Not true, but just for testing if (4 == b) cout << "Equal" << endl; Equal
y = ob.y + 100; // Not true, but just for testing else cout << "Not equal" << endl;
32 42
return *this; 228 248
}
112 122
18
Passing Reference Parameter for Operator Overloading in C++

➢ Passing a reference parameter has two advantages- ✓ Changes of object impacted


(1) passing the address of an object is always quick and efficient. the calling function.
(2) to avoid the trouble caused when a copy of an operand is destroyed. ✓ Better to use const if object
#include <iostream> int main(){ changed is not required.
using namespace std; coord a(10, 20), b(30, 40), c;
int x, y;
class coord {
int x, y; (a+b).getxy(x, y); Note:
public: cout << x << " " << y << endl;
coord(int i = 0, int j = 0) { x = i; y = j;} ➢ (a + b).getxy(x,y);
void getxy(int &i, int &j) { i = x; j = y;} c = a = b;
coord operator + (coord &ob){ c.getxy(x, y); ✓ a & b are not changed.
coord temp; cout << x << " " << y << endl;
temp.x = x + ob.x; a.getxy(x, y); ✓ A temporary object is
temp.y = y + ob.y; cout << x << " " << y << endl; created to return the
return temp; object, and is destroyed
} return 0;
coord operator = (const coord &ob){ } OUTPUT: after the execution of
x = ob.x; 40 60 (a + b).getxy(x,y);
y = ob.y; 30 40
return *this; 30 40
}
}; 19
Returning Reference for Operator Overloading in C++
(1) Assignment Operator:
✓ Returning Reference is built-in for assignment operators (=, +=, -=, *=, /=).
✓ Hence, to maintain consistency, returning reference should be used for assignment operator for better
understanding.

(2) Increment (++) / Decrement (--) Operator:


✓ Prefix version (++ob, --ob) should return a reference to the modified object.
✓ Postfix version (ob++, ob++) should return a copy of the object before modification.

(3) Input / Output Stream Operator ( >> or <<):


✓ Return a reference to the ostream or istream object.

20
Returning Reference for Operator Overloading in C++
#include <iostream> Coord &Coord:: operator += (Coord &ob){
using namespace std; x += ob.x;
y += ob.y;
class Coord{ return *this;
int x, y; }
public:
Coord(int a=0, int b=0){ x = a; y = b;} ostream &operator<<(ostream &out, const Coord &ob) {
out << "(" << ob.x << ", " << ob.y << ")";
Coord &operator += (Coord &ob); return out;
friend ostream &operator<<(ostream &out, const Coord &ob); }
friend istream &operator>>(istream &in, Coord &ob);
istream &operator>>(istream &in, Coord &ob) {
Coord &operator ++(){ cout << "Enter coordinates (x y): ";
++x; in >> ob.x >> ob.y;
++y; return in; int main(){
return *this; } Coord a(10, 20), b;
} int x, y;

Coord operator ++(int){ cin >> b;


x++; cout << b << endl;
OUTPUT: a += b;
y++; Enter coordinates (x y): 3 4
return *this; cout << a << endl;
(3, 4)
} (13, 24)
}; return 0;
}
21
Problem with Returning Reference for Operator Overloading in C++
❖ Arithmetic Operator (+, -, *, /, %) typically creates new object as the result of the operation
and should return the new object by value.
❖ Returning a Reference for arithmetic operator would be problematic because the refenced
object would likely to be a temporary that goes out of scope. int main(){
#include <iostream> Coord a(10, 20), b(30, 40), c;
using namespace std; int x, y;

class Coord{ (a+b).getxy(x, y);


int x, y; cout << x << " " << y << endl;
public:
Coord(int a=0, int b=0){ x = a; y = b;} c = a + b;
void getxy(int &i, int &j){ i = x; j = y;} c.getxy(x, y);
cout << x << " " << y << endl;
Coord &operator + (Coord &ob){ a.getxy(x, y);
Coord temp; cout << x << " " << y << endl;
temp.x = x + ob.x; OUTPUT: b.getxy(x, y);
temp.y = y + ob.y; -1121524120 32759 //Why cout << x << " " << y << endl;
return temp; 40 60
} 10 20 return 0;
30 40 }
}; 22
All Operator Overloading in C++ using Friend Function

Consider the overloaded operator function,


ob1 = ob2 + 100; // can be implemented as a member or friend
ob1 = 100 + ob2; //Only be implemented using a friend method.

➢ Using friend operator function, flexibility can be added.


➢ A friend function does not have a “this” pointer.
➢ All the operands are passed explicitly to the friend method.
➢ Any modifications inside the friend method will not affect the object that is passed
during the call. To ensure changes, reference parameter is used, if necessary.

23
Friend Function for Operator Overloading in C++
#include <iostream> Coord operator+(int n, const Coord& c) {
using namespace std; return Coord(n + c.x, n + c.y);
}
class Coord{
int x, y; Coord operator++(Coord& c) { int main(){
public: ++c.x; Coord c1(1, 2), c2(3, 4);
Coord(int x = 0, int y = 0) : x(x), y(y) {} ++c.y; Coord c3 = c1 + c2;
void show() const { cout << "(" << x << ", " << y << ")" << endl; } return c; c3.show();
}
friend Coord operator+(const Coord& c1, const Coord& c2); Coord c4 = c1 + 5;
friend Coord operator+(const Coord& c, int n); Coord operator++(Coord& c, int) { c4.show();
friend Coord operator+(int n, const Coord& c); ++c.x;
friend Coord operator++(Coord& c); ++c.y; Coord c5 = 5 + c1;
friend Coord operator++(Coord& c, int); return c; c5.show();
}; }
++c1;
Coord operator+(const Coord& c1, const Coord& c2) { c1.show();
return Coord(c1.x + c2.x, c1.y + c2.y); OUTPUT:
} (4, 6) c1++;
(6, 7) c1.show();
Coord operator+(const Coord& c, int n) { (6, 7)
return Coord(c.x + n, c.y + n); (2, 3) return 0;
} (3, 4) }

24
Assignment Operator
➢By default, when an assignment operator applied to an object, a bitwise copy is made. So, there is no need
to write own assignment operator.
➢In case of dynamic memory allocation, bitwise copy is not desirable and still need to write assignment
operator.
#include <iostream> int main(){
#include <cstring> strtype a("Hello"), b("There");
strtype:: strtype(char *s){
#include <cstdlib> int l;
using namespace std; cout<< a.get()<< " " << b.get()<< endl;
l = strlen(s) + 1;
a = b;
p = new char[l];
class strtype{ cout<< a.get()<< " " << b.get()<< endl;
strcpy( p, s );
char *p; len = l;
int len; return 0;
}
public: }
strtype(char *s); strtype &strtype:: operator = (strtype &ob){
~strtype() { delete [] p;} p = new char[ob.len]; OUTPUT:
char *get() { return p; } len = ob.len; Hello There
strtype &operator = (strtype &ob); strcpy(p, ob.p); There There
}; return *this;
}
25
Overloading Array Subscript Operator []

➢ The general format of array subscript operator is as follows:


int &operator [] (int i);

P5
P6
P2

P1 P3

26
Overloading Array Subscript Operator []
#include <iostream>
using namespace std;
const int arraySize = 2; int main(){
Point p1(3,4);
class Point {
int *arr; p1.print();
public: p1[0] = 6;
Point(int x = 0, int y = 0){ p1[1] = 8;
arr = new int[arraySize]; p1.print();
arr[0] = x;
arr[1] = y; return 0;
} }

int& operator[](int pos){


if (pos < arraySize) return arr[pos];
else{ OUTPUT:
cout << "Out of bound" << endl; (3,4)
exit(0); (6,8)
}
}

void print(){
cout << "(" << arr[0] << "," << arr[1] << ")" << endl;
}
};
27
Type Conversion in C++
➢Type conversion from the type of argument to the type of class is of two types:
✓ implicit and
✓ explicit.
➢Type Conversion:
myclass ob(4); //supported by both type of conversion
myclass ob = 4; //not supported by explicit conversion

int main(){
#include <iostream>
Myclass ob1(10);
#include <cstdlib> OUTPUT:
// Myclass ob2 = 20; Error, Why?
using namespace std;
Myclass ob3("40"); ob1: 10
Myclass ob4 = "60"; // Ok, Why? ob3: 40
class Myclass{
ob4: 60
int a;
cout << "ob1: " << ob1.getA() << endl;
public:
cout << "ob3: " << ob3.getA() << endl;
explicit Myclass(int x){ a=x; }
cout << "ob4: " << ob4.getA() << endl;
Myclass(char *str){ a=atoi(str); }
int getA(){ return a; }
return 0;
};
}

28
Conversion Function in C++
➢ A conversion function automatically converts an object into a compatible value.
operator type() { return value;}
#include <iostream>
#include <cstring>
int main(){
using namespace std;
Rectangle r("Rectangle", 5, 10);
double area = r;
class Rectangle{
cout << "Area: " << area << endl;
char name[20];
char* name = r;
int length;
cout << "Name: " << name << endl;
int wide;
return 0;
public:
}
Rectangle(char *name, int length, int wide){
strcpy(this->name, name);
this->length = length;
this->wide = wide; OUTPUT:
} Area: 50
operator double(){ Name: Rectangle
return length * wide;
}
operator char*(){
return name;
}
};
29
Overloading in Java

Java doesn’t support customized


operator overloading.

Conversion Function in C++ =>


Auto Unboxing in Java

30
Auto-Boxing and Auto Unboxing in Java
public class Main {
public static void main(String[] args) {
➢Java wrapper wraps primitive types into Integer iOb1 = Integer.valueOf(100);
Objects. The available wrappers are- Integer iOb2 = 150;
double num1 = iOb1;
Double, Float, Long, Integer,
int num2 = iOb2.intValue();
Short, Byte, Character and Boolean double sum1 = num1 + num2;
int sum2 = iOb1 + iOb2;
double num = iOb1.doubleValue();
➢ Auto Boxing wraps primitive types into the
respective Objects and unboxing unwraps System.out.println("Primitive Sum: "+ sum1);
Objects into primitive types. System.out.println("Object sum: " + sum2);
System.out.println("Primitive Sum: "+ num1 + num2);
System.out.println("Object sum: " + iOb1 + iOb2);
System.out.println(num);
➢ Two type of methods: }
valueOf() -> convert value to object. }
typeValue() -> convert object to primitive type.
OUTPUT:
Primitive Sum: 250.0
Object sum: 250
Primitive Sum: 100.0150
Object sum: 100150
100.0
31

You might also like