Polymorphism in Object Oriented Programming
Polymorphism in Object Oriented Programming
Constructor Overloading
• In C++, We can have more than one constructor in a class with same name, as
long as each has a different list of arguments. This concept is known as
Constructor Overloading and is quite similar to function overloading.
• Overloaded constructors essentially have the same name (exact name of the class)
and differ by number and type of arguments.
• A constructor is called depending upon the number and type of arguments passed.
• While creating the object, arguments must be passed to let compiler know, which
constructor needs to be called.
// Constructor overloading
#include <iostream> void disp()
using namespace std; {
class construct cout<< area<< endl;
{ }
public: };
float area; int main()
// Constructor with no parameters {
construct() // Constructor Overloading
{ construct o;
area = 0; construct o2( 10, 20);
} o.disp();
// Constructor with two parameters o2.disp();
construct(int a, int b) return 1;
{ }
area = a * b;
}
// C++ program to demonstrate constructor age = a;
overloading
}
#include <iostream>
using namespace std;
int getAge() {
return age;
class Person {
}
private:
};
int age;
int main() {
public:
Person person1, person2(45);
// 1. Constructor with no arguments
Person() {
cout << "Person1 Age = " << person1.getAge()
age = 20; << endl;
} cout << "Person2 Age = " << person2.getAge()
<< endl;
// 2. Constructor with an argument
Person(int a) { return 0;
}
// C++ program to demonstrate constructor overloading // 3. Constructor with one argument
#include <iostream> Room(double len) {
using namespace std; length = len;
breadth = 7.2;
class Room { }
private: double calculateArea() {
double length; return length * breadth;
double breadth; }
public: };
// 1. Constructor with no arguments int main() {
Room() { Room room1, room2(8.2, 6.6), room3(8.2);
length = 6.9; cout << "When no argument is passed: " << endl;
breadth = 4.2; cout << "Area of room = " << room1.calculateArea() << endl;
} cout << "\nWhen (8.2, 6.6) is passed." << endl;
// 2. Constructor with two arguments cout << "Area of room = " << room2.calculateArea() << endl;
Room(double l, double b) { cout << "\nWhen breadth is fixed to 7.2 and (8.2) is passed:" <<
endl;
length = l;
cout << "Area of room = " << room3.calculateArea() << endl;
breadth = b;
return 0;
}
}
Operator Overloading
// Overload ++ when used as prefix and postfix
void display() {
#include <iostream> cout << "Count: " << value << endl;
using namespace std; }
class Count { };
private: int main() {
int value; Count count1;
public:
// Constructor to initialize count to 5 // Call the "void operator ++ (int)" function
Count() : value(5) {} count1++;
// Overload ++ when used as prefix count1.display();
void operator ++ () {
++value; // Call the "void operator ++ ()" function
} ++count1;
// Overload ++ when used as postfix
void operator ++ (int) { count1.display();
value++; return 0;
} }
// C++ program to overload the binary operator + // Overload the + operator int main() {
// This program adds two complex numbers Complex operator + (const Complex& obj) { Complex complex1, complex2, result;
#include <iostream> Complex temp;
using namespace std; temp.real = real + obj.real; cout << "Enter first complex number:\n";
class Complex { temp.imag = imag + obj.imag; complex1.input();
private: return temp;
float real; } cout << "Enter second complex number:\n";
float imag; complex2.input();
public: void output() {
// Constructor to initialize real and imag to 0 if (imag < 0) // complex1 calls the operator function
Complex() : real(0), imag(0) {} cout << "Output Complex number: " << real << // complex2 is passed as an argument to the
imag << "i"; function
void input() {
else result = complex1 + complex2;
cout << "Enter real and imaginary parts
respectively: "; cout << "Output Complex number: " << real << result.output();
"+" << imag << "i";
cin >> real;
}
cin >> imag; return 0;
};
} }
A Simple Example to Access Private Members of Other Class
#include <iostream>
using namespace std;
class Exmp_A{
int i =3;
// Declaring the friend class
friend class Exmp_B;
};
class Exmp_B
{
public:
void display(Exmp_A &a)
{
cout<<"The value of i is : "<<a.i;
}
};
int main(){
Exmp_A a;
Exmp_B b;
b.display(a);
return 0;
}
Output:
The value of i is : 3
As you can see in the output, Class Exmp_B could access the private data member i of class Exmp_A as it was a
friend class.
#include <iostream>
using namespace std;
class Exmp_A{
private:
int x;
// Declaring the friend class
friend class Exmp_B;
public:
// Initializing x value using a constructor
Exmp_A() : x(9) {}
};
class Exmp_B{
private:
int y;
public:
// Initializing y value using a constructor
Exmp_B() : y(13) {}
// Function to perform addition
int sum(){
Exmp_A a;
return a.x + y;
}
};
int main()
{
Exmp_B b;
cout << "Sum is: " << b.sum();
return 0;
}
Output:
Sum is : 22
#include <iostream>
using namespace std;
class Example{
// A private member by default
string s;
public:
friend void show( Example value );
void input( string val );
};
void Example::input( string val ){
s = val;
}
void show( Example value ){
cout<<"Value of private string data is : "<<value.s<<endl;
}
int main(){
cout<<"Welcome to Simplilearn!"<<endl<<endl;
Example value;
value.input("Simplilearn");
// Using friend function to display string
show( value );
return 0;
}
Output:
Welcome to Simplilearn!
Value of private string data is : Simplilearn
#include <iostream>
using namespace std;
class Example{
private:
int length;
public:
Example(): length(0) {}
friend int printLength(Example); //friend function
};
int printLength(Example e){
e.length = 20;
return e.length;
}
int main(){
Example e;
cout<<"Length of Example box: "<< printLength(e)<<endl;
return 0;
}
Output:
Length of Example box : 20
#include <iostream>
using namespace std;
class base {
public:
void display(int num) {
cout << "Num: " << num << endl;
}
void display(int num1, int num2 = 10) {
cout << "Num1: " << num1 << "Num2: " << num2 << endl;
}
void setValue(int num) {
cout << "int Num: " << num << endl;
}
void setValue(float num) {
cout << "Float Num: " << num << endl;
}
static void displayValue(int num) {
cout << "static int Num: " << num << endl;
}
static void displayValue(int num1, int num2) {
cout << "static Num: " << num1 << endl;
}
void displayInt(int num) {
cout << "static int Num: " << num << endl;
}
void displayInt(int& num) {
cout << "static Num: " << num << endl;
}
};
int main()
{
base b;
int i = 10;
b.display(10); //Error: Ambiguous, Reason: Since both the display candidates fits here
b.display(10, 20);
b.setValue(50);
b.setValue(10.0); //Error: Ambiguous, Reason: By default, this is double and double can be converted to float or int
b.setValue(10.0f);
b.displayValue(10);
b.displayInt(i); // Error: Ambiguous, Reason: Based on whether argument is caught with or without reference, does not result in overloading.
return 0;
}
For the following scenarios, function overloading is not possible
1) Difference in Return Type
int getValue() {}
void getValue() {}
The above two functions have same prototype except return type. Such kind of function cannot be overloaded.
2) Difference in constness of the parameter
void display(int num) {}
void display(const int num) {}
3) Difference in static keyword
void display(int num) {}
static void display(int num) {}
#include<iostream.h> };
class class-2; void exchange ( class-1 &x, class-2 &y)
class class-1{ {int temp=x. value 1;x. value I=y.valuo2; y.value2=temp;}
int value 1; int main( )
public: {class-1 c1
void indata( int a) ;class-2 c2
{ value=a; } ;c1.indata(l00);c2.indata(200);
void display(void) { cout<<value<<endl; } cout<<”values before exchange:”<<endl;
friend void exchange ( class-1 &, class-2 &); c1.display();
}; c2.display( );
class class-2 exchange (c1,c2);
{int value2; cout<<”values after exchange :”<<endl;
public: c1. display ();
void indata( int a) c2. display ( );
{ value2=a; } return(0);
void display(void) }
{ cout<<value2<<endl; } output:values before exchange 100 200values after
exchange 200100
friend void exchange(class-l & , class-2 &);
#include<iostream> sum(int a,int b);
class sum sum(int a, float d,double c);
{ };
Private: sum :: sum(int x,int y)
int a; int b; int c; float d; double e; {a=x;b=y;}
public: sum :: sum(int p, float q ,double r)
sum ( ) {a=p; d=q; e=r;}
{cout<<”enter a”; void main( )
cin>>a; { sum 1;sum m=sum(20,50);
cout<<”enter b”; sum n= sum(3,3.2,4.55);
cin>>b; }
cout<<”sum= “<<a+b<<endl; output: enter a : 3 enter b : 8 sum=11
} sum=70 sum=10.75
#include <iostream>
#include <cstring>
using namespace std;
int main () {
char str1[10] = "Hello";
char str2[10] = "World";
char str3[10];
int len ;
// copy str1 into str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
// concatenates str1 and str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
// total lenghth of str1 after concatenation
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
Output
return 0;
• strcpy( str3, str1) : Hello
}
• strcat( str1, str2): HelloWorld
• strlen(str1) : 10
#include <iostream>
#include <string>
int main () {
string str3;
int len ;
str3 = str1;
cout << "str3.size() : " << len << endl; • str3 : Hello
}
• str3.size() : 10
Virtual Functions
• As mentioned earlier, polymorphism refers to the property by which objects belonging to
different classes are able to respond to the same message, but in different forms.
• An essential requirement of polymorphism is therefore the ability to refer to objects without
any regard to their classes.
• This necessitates the use of a single pointer variable to refer to the objects of different classes.
• Here, we use the pointer to base class to refer to all the derived objects.
• But, we just discovered that a base pointer, even when it is made to contain the address of a
derived class, always executes the function in the base class.
• The compiler simply ignores the contents of the pointer and chooses the member function that
matches the type of the pointer.
• How do we then achieve polymorphism?
• It is achieved using what is known as 'virtual functions’.
• When we use the same function name in both the base and derived
classes, the function in base class is declared as virtual using the
keyword virtual preceding its normal declaration.
• When a function is made virtual, C++ determines which function to
use at run time based on the type of object pointed to by the base
pointer, rather than the type of the pointer.
• Thus, by making the base pointer to point to different objects, we can
execute different versions of the virtual function.
This program illustrates as follows
#include <iostream {
using namespace std; Base B;
class Base Derived D;
{ Base *bptr;
public: cout << “\n bptr points to Base \n “;
void display() {cout << "\n Display base";} bptr = &B;
virtual void show() {cout << "\n show base":} bptr -> display(); // calls Base version
}; bptr -> show(); // calls Base version
class Derived : public Base cout << "\n\n bptr points to Derived\n";
{ bptr = &D;
public: bptr -> display(); // calls Base version
void display() {cout << "\n Display derived“;} bptr -> show() ; //calls Derived version
void show() {cout << "\n show derived“;} return 0;
}; •} The output of Program would be: