multipath inheritance or virtual base class
#include<iostream.h>
class Student
{
protected:
int rollno;
public:
void getno()
{
cout<<"enter the rollno";
cin>>rollno;
}
};
class Test:virtual public Student
{
protected:
int marks[5];
public:
void getmarks()
{
cout<<"enter five subject marks";
for(int i=0;i<5;i++)
{
cin>>marks[i];
}
}
};
class Sports:public virtual Student
{
protected:
int score;
public:
void getscore()
{
cout<<"enter the sports score";
cin>>score;
}
};
class Result:public Test,public Sports
{
int total;
public:
void compute()
{
total=0;
for(int i=0;i<5;i++)
{
total+=marks[i];
}
total=total+score;
}
void display()
{
cout<<"Roll No"<<rollno<<endl;
cout<<"Marks"<<endl<<"SUB1="<<marks[0];
cout<<"SUB2="<<marks[1]<<"SUB3="<<marks[2];
cout<<"SUB4="<<marks[3]<<"SUB5="<<marks[4]<<endl;
cout<<"Sports score="<<score;
cout<<endl<<"Total="<<total;
}
};
int main()
{
Result ob;
[Link]();
[Link]();
[Link]();
[Link]();
[Link]();
return 0;
}
Polymorphism means "one interface, multiple implementations"
Polymorphism is either static or dynamic.
In static or compile-time polymorphism, the function code to be executed for a function
call is known in advance, i.e., the binding is done early during compilation.
Function overloading and Operator overloading belong to early binding.
In dynamic or run-time polymorphism the binding of function to a call is deferred until
runtime, i.e., dynamic or late binding.
Runtime polymorphism is achieved through virtual functions
Function Overloading
C++ permits designing a family of functions with one function name but with
different argument lists is known as function overloading or function
polymorphism.
The list should differ on type and count.
When a call is made, the function to be invoked is determined by the
compiler after finding a unique match of corresponding prototype.
In case if there is no exact match for a function call then the compiler tries to
find a match by
1. making integral promotions to actual arguments (char to int, float to double)
2. using built-in conversion routines
3. If it does not result in a unique match then ambiguity error is reported.
#include <iostream.h>
const float pi = 3.14;
int volume(int); // cube volume
int volume(int, int, int); // box volume
float volume(int, int); // cylinder volume
int main()
{
cout << "Cube volume : " << volume(5) << "\n";
cout << "Box volume : " << volume(9, 3, 4) << "\n";
cout << "Cylinder volume : " << volume(5, 6) << "\n";
return 0;
}
int volume(int a)
{
return (a*a*a);
}
int volume(int l, int b, int h)
{
return (l * b * h);
}
float volume(int r, int h)
{
return (pi * r * r * h);
}
o/p:
Cube volume : 125
Box volume : 108
Cylinder volume : 471
Operator overloading
operator overloading refers giving special meaning to an existing operator so that it could be
applied to user-defined types.
The operator() function can be either a member function or friend function, but cannot be static.
Friend function cannot be used to overload operators = () [] ->
An operator's semantic can be extended but its syntax must not be altered.
Operator overloading is accomplished using a special operator() function.
returntype classname::operator symbol(arguments)
{
// code for overloading
}
Operators that cannot be overloaded
1. class member access operator(.)
[Link] resolution operator(::)
[Link] operator
[Link] operator(?:)
The overloaded operator must have at least one operand of class type.
Unary operator overloading:
o Member function- takes no arguments and return type is void.
o Friend function-takes object reference as argument and return type is void.
Binary operator overloading:
o Member function - takes one argument and return type is of class type. The left side operand
must be of class type.
o Friend function - takes two arguments and return type is of class type.
// Unary operator overloading
#include <iostream.h>
class space
{
int x;
int y;
int z;
public:
space(int a, int b, int c)
{
x = a;
y = b;
z = c;
}
void display()
{
cout << x << y << z;
}
void operator-();
};
void space::operator-() // operator overloading function
{
x = -x;
y = -y;
z = -z;
}
int main()
{
space S(1, 2, -3);
-S; // operator – invoked on class type
[Link]();
return 0;
}
o/p:
-1 -2 3
Binary operator overloading
Binary operator overloaded using member function takes an argument of class type and returns a
class type.
The left operand is passed implicitly to the operator function using this pointer, whereas the right
operand is explicitly passed.
The left operand must be of class type, since it is the invoking object.
Final result is stored in a temporary object and returned.
//overloading binary operator
#include<iostream.h>
class complex
{
int real,imag;
public:
void read()
{
cout<<"enter the complex number";
cin>>real>>imag;
}
void display()
{
cout<<real<<"+i"<<imag;
}
complex operator+(complex);
};
complex complex::operator+(complex ob)
{
complex temp;
[Link]=real+[Link]; //[Link]+[Link]
[Link]=imag+[Link]; //[Link]+[Link]
return temp;
}
int main()
{
complex c1,c2,c3;
[Link]();
[Link]();
c3=c1+c2;//c3=[Link]+(c2);
[Link]();
}
o/p:
enter the complex number 5 1
enter the complex number 5 2
10+i3
Early vs. Late Binding:
Early Binding:
Early binding refers to events that occur at compile time.
In essence, early binding occurs when all information needed to call a function is known
at compile time. (Put differently, early binding means that an object and a function call
are bound during compilation.)
Examples of early binding include normal function calls (including standard library
functions), overloaded function calls, and overloaded operators.
The main advantage to early binding is efficiency. Because all information necessary to
call a function is determined at compile time, these types of function calls are very fast.
Late Binding:
The opposite of early binding is late binding.
As it relates to C++, late binding refers to function calls that are not resolved until run
time. Virtual functions are used to achieve late binding.
As you know, when access is via a base pointer or reference, the virtual function actually
called is determined by the type of object pointed to by the pointer. Because in most
cases this cannot be determined at compile time, the object and the function are not
linked until run time.
The main advantage to late binding is flexibility.
Unlike early binding, late binding allows you to create programs that can respond to
events occurring while the program executes without having to create a large amount of
"contingency code."
What is overriding in inheritance. Give an example.
Derived class can redefine base class member functions, by having member
functions of the same prototype as in the base class. This redefinition is
known as overriding.
When a redefined member function is called using a derived object, only the
derived class member function gets executed.
#include <iostream.h>
class base
{
public:
void display()
{
cout << "Base class member function";
}
};
class derived : public base
{
public:
void display() // base class function overridden
{
cout << "Derived class member function";
}
};
int main()
{
derived d1;
[Link]();
return 0;
}
o/p:
Derived class member function
Differentiate overloading and overriding
Why do we need virtual function?
Even if base class pointer holds address of a derived object, it still executes
base class member function. The compiler selects function based on type of
pointer.
Therefore, virtual function is required to solve this anomaly and to support
run-time Polymorphism
#include<iostream.h>
class base
{
public:
void func()
{
cout<<"base class function";
}
};
class derived:public base
{
public:
void func()
{
cout<<"derived class function";
}
};
int main()
{
base *ptr;
derived ob;
ptr=&ob;
ptr->func();
return 0;
}
o/p:
base class function
virtual function
A virtual function is a base class member function preceded by the keyword
virtual and redefined by a derived class.
Virtual function in the base class defines interface of the function.
Each redefinition of the virtual function by a derived class implements "one
interface, multiple methods", i.e., polymorphism.
When a base pointer points to a derived object, C++ determines which
version of that function to execute based upon type of object pointed to at
run-time (late binding).
When different derived objects are pointed to, different versions of the
virtual function are executed (dynamic binding)
Rules
Virtual functions must be a member function.
It cannot be qualified as static.
It can be a friend of another class
Virtual functions usually involve hierarchical inheritance.
Virtual functions are accessed using pointers of base class type.
Prototype of base class virtual function and all derived class versions must
be identical. Otherwise it would be treated as overloaded function.
A base pointer can point to a derived object, whereas vice versa is not true.
A virtual function need not be redefined in the derived class. In such cases,
base class functions would be executed.
Constructors cannot be virtual, whereas destructors can be virtual.
#include<iostream>
using namespace std;
class base
{
public:
virtual void func()
{
cout<<"base class function"<<endl;
}
};
class derived1:public base
{
public:
void func()
{
cout<<"derived1 class function"<<endl;
}
};
class derived2:public base
{
public:
void func()
{
cout<<"derived2 class function"<<endl;
}
};
int main()
{
base *ptr,ob;
derived1 ob1;
derived2 ob2;
ptr=&ob;
ptr->func();
ptr=&ob1;
ptr->func();
ptr=&ob2;
ptr->func();
return 0;
}
o/p:
base class function
derived1 class function
derived2 class function
Pure Virtual Functions or Abstract Classes:
Pure virtual functions are used
if a function doesn't have any use in the base class
but the function must be implemented by all its derived classes
A pure virtual function is a virtual function that has no definition within the base class. To
declare a pure virtual function, use this general form:
virtual type func-name(parameter-list) = 0;
When a virtual function is made pure, any derived class must provide its own definition. If the
derived class fails to override the pure virtual function, a compile-time error will result.
Abstract Classes:
A class that contains at least one pure virtual function is said to be abstract.
We cannot create objects of an abstract class. However, we can derive classes from them(you
can create pointers and references to an abstract class), and use their data members and member
functions (except pure virtual functions).
class shape
{
protected:
int b,h;
public:
void get()
{
cin>>b>>h;
}
virtual void area()=0;
};
class rectangle:public shape
{
public:
void area()
{
cout<<"rectangle area:"<<b*h<<endl;
}
};
class triangle:public shape
{
public:
void area()
{
cout<<"triangle area:"<<0.5*b*h;
}
};
int main()
{
shape *ptr;
rectangle r;
ptr=&r;
ptr->get();
ptr->area();
triangle t;
ptr=&t;
ptr->get();
ptr->area();
return 0;
}
o/p:
5 4
Rectangle area : 20
5 3
Triangle area : 7.5