0% found this document useful (0 votes)
13 views33 pages

Function and Operator Overloading

This document covers key concepts of C++ including function and operator overloading, inheritance, and polymorphism. It explains how C++ allows multiple definitions for functions and operators, the importance of inheritance for code reusability, and the distinction between compile-time and run-time polymorphism. Additionally, it details the syntax for implementing these features and the rules governing operator overloading and inheritance access specifiers.

Uploaded by

pravanshuadc
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)
13 views33 pages

Function and Operator Overloading

This document covers key concepts of C++ including function and operator overloading, inheritance, and polymorphism. It explains how C++ allows multiple definitions for functions and operators, the importance of inheritance for code reusability, and the distinction between compile-time and run-time polymorphism. Additionally, it details the syntax for implementing these features and the rules governing operator overloading and inheritance access specifiers.

Uploaded by

pravanshuadc
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

Unit - 4

Overloading
• C++ allows you to specify more than one definition for a function name or an operator in the same scope, which is
called function overloading and operator overloading respectively.

function overloading
• One way that C++ achieves polymorphism is through the use of function overloading. In C++, two or more functions
can share the same name as long as their parameter declarations are different.
• In this situation, the functions that share the same name are said to be overloaded, and the process is referred to as
function overloading.
• To see why function overloading is important, first consider three functions defined by the C subset: abs( ),
labs( ), and fabs( ). The abs( ) function returns the absolute value of an integer, labs( ) returns the absolute
value of a long, and fabs( ) returns the absolute value of a double.
• Although these functions perform almost identical actions, in C three slightly different names must be used
to represent these essentially similar tasks.
• Even though the underlying concept of each function is the same, the programmer has to remember three
things, not just one. However, in C++, you can use just one name for all three functions.
#include <iostream> int abs(int i)
using namespace std; {
// abs is overloaded three ways cout << "Using integer abs()\n";
return i<0 ? -i : i;
int abs(int i); }
double abs(double d);
long abs(long l); double abs(double d)
{
int main() cout << "Using double abs()\n";
{ return d<0.0 ? -d : d;
cout << abs(-10) << "\n"; }
cout << abs(-11.0) << "\n"; long abs(long l)
cout << abs(-9L) << "\n"; {
return 0; cout << "Using long abs()\n";
return l<0 ? -l : l;
}
}
Examples
void display(); //function with no arguments
void display( int ); //function with one integer type arguments
void display( float ); //function with one floating point arguments
void display( int, float ); //function with one floating and one integer type arguments
#include <iostream>
using namespace std;
void display ( ) //function with no arguments
int main()
{ {
int a = 3; display(); //function call with no arguments
cout << a << endl; display(5); //function call with one integer argument
} display(2.3); //function call with one floating argument
void display (int a ) //function with one integer argument display(5,4.0); //function call with one integer and one
{ floating arguments
cout << a << endl; return 0;
} } //end of program
void display (double a ) //function with one floating argument
{
cout << a << endl;
}
void display(int a, float b) //function with one integer and one floating arguments
{
cout<< a << " , " << b << endl;
}
Operator Overloading
• C++ operator overloading is one of the most powerful features of C++ that
allows a user to change the way the operator works.
• Operator overloading is not automatic—you must write operator-overloading
functions to perform the desired operations.
• An operator is overloaded by writing a nonstatic member function definition or
non-member function definition as you normally would, except that the function
name starts with the keyword operator followed by the symbol for the operator
being overloaded.
• For example, the function name operator+ would be used to overload the addition
operator (+) for use with objects of a particular class. When operators are
overloaded as member functions, they must be non-static, because they must be
called on an object of the class and operate on that object.
Rules and Restrictions on Operator Overloading
• As you prepare to overload operator with your own classes, there are several rules and restrictions you should
keep in mind:
• The precedence of an operator cannot be changed by overloading. However, parentheses can be used to force
the order of evaluation of overloaded operators in an expression.
• The associativity of an operator cannot be changed by overloading—if an operator normally associates from
left to right, then so do all of its overloaded versions.
• You cannot change the “arity” of an operator (that is, the number of operands an operator takes)—overloaded
unary operators remain unary operators; overloaded binary operators remain binary operators. Operators &, *,
+ and - all have both unary and binary versions; these unary and binary versions can be separately overloaded.
• You cannot create new operators; only existing operators can be overloaded.
• The meaning of how an operator works on values of fundamental types cannot be changed by operator
overloading. For example, you cannot make the + operator subtract two ints. Operator overloading works only
with objects of user-defined types or with a mixture of an object of a user-defined type and an object of a
fundamental type.
• Related operators, like + and +=, must be overloaded separately.
• When overloading (), [], -> or any of the assignment operators, the operator overloading function must be
declared as a class member. For all other overloadable operators, the operator overloading functions can be
member functions or non-member functions.
• To define an additional task to an operator, specify what it means in relation to the class to which the operator
is applied. This is done with the help of a special function, called operator function.
• The process of overloading involves following steps:
1. Create a class that defines the data type that is to be used in the overloading operation.
2. Declare the operator function operator op() in the public part of the class. It may be a member function or a
friend function.
3. Here op is the operator to be overloaded.
4. Define the operator function to implement the required operations.
• General Form:- Ex:
return-type classname :: operator op(arglist) complex complex::operator+(complex c)
{
{
complex t;
Function body [Link]=real+[Link];
} [Link]=img+[Link];
return t;
}
• Operator functions are either Member functions(non-static) or friend function.
• For Member function no arguments for unary operator, one argument for binary operator.
• For friend member function one argument for unary operator, two argument for binary
operator.
• This is because, the object is used to invoke the member function is passed implicitly, therefore is
available for the member function.
• This is not with friend function, arguments may be passed either by value or by reference.
• Operator functions are declared as
vector operator+(vector); //vector addition
Vector operator-(); // unary minus
Friend vector operator+(vector, vector); // vector addition
Friend vector operator-(vector); //unary minus

• Overloaded operator functions can be invoked(called) by


op X or X op // unary operator, interpreted as operator op(X) (for friend function)

X op Y // binary operator , interpreted as [Link] op(Y) (for member function) or operator


op(X,Y) ( for friend function)
• Overloading unary operator
To overload a minus operator when used as a unary, takes just one operand; to change the sign of an operator

unary minus, can be used on objects by overloading , similar to variables

when applied on object it will change sign of each of its data item.

• Syntax for Unary Operator (Inside a class) • Syntax for Unary Operator (Outside a class)
return-type operator operatorsymbol( ) return-type classname::operator operatorsymbol( )
{ {
//body of the function //body of the function
} }

Ex:
void operator-() Ex:
{
real=-real; void complex::operator-()
img=-img; {
} real=-real;
img=-img;
}
Overloading binary operator

• An binary operator means, an operator which works on two operands. For example, + is an binary operator, it takes single operand
(c+d). So, when overloading an binary operator, it takes one argument (one is object itself and other one is passed argument).
• Syntax for Binary Operator (Inside a class)
return-type operator operatorsymbol(argument)
{
//body of the function
}

• Syntax for Binary Operator definition (Outside a class)


return-type classname::operator operatorsymbol(argument)
{
//body of the function
}

Overloading + operator:
C= Sum(A, B); // function notation was used in addition of complex numbers
C= A + B; // arithmetic notation, by overloading the + operator using an operator +() function
Inheritance
• Inheritance is one of the most important features of Object-Oriented Programming.
• Inheritance is a feature or a process in which, new classes are created from the existing classes. The
new class created is called “derived class” or “child class” and the existing class is known as the
“base class” or “parent class”. The derived class now is said to be inherited from the base class.
• When we say derived class inherits the base class, it means, the derived class inherits all the
properties of the base class, without changing the properties of base class and may add new
features to its own. These new features in the derived class will not affect the base class. The
derived class is the specialized class for the base class.
• Sub Class: The class that inherits properties from another class is called Subclass or Derived
Class.
• Super Class: The class whose properties are inherited by a subclass is called Base Class or
Superclass.
Why and when to use inheritance?
• Consider a group of vehicles.
You need to create classes for
Bus, Car, and Truck.
• The methods fuelAmount(),
capacity(), applyBrakes() will be
the same for all three classes.
• If we create these classes
avoiding inheritance then we
have to write all of these
functions in each of the three
classes as shown below figure:

You can clearly see that the above process results in duplication of the same code 3
times. This increases the chances of error and data redundancy. To avoid this type of
situation, inheritance is used. If we create a class Vehicle and write these three
functions in it and inherit the rest of the classes from the vehicle class, then we can
simply avoid the duplication of data and increase re-usability. Look at the below
diagram in which the three classes are inherited from vehicle class:
Using inheritance, we have to write the functions only one time instead of
three times as we have inherited the rest of the three classes from the
base class (Vehicle).

Implementing inheritance in C++: For creating a sub-class that is inherited from the base class we have to follow the below syntax.
Derived Classes: A Derived class is defined as the class derived from the base class.
Syntax:
class <derived_class_name> : <access-specifier> <base_class_name>
{
//body
}
Access Specifiers

In C++, there are three access specifiers:


•public - members are accessible from outside the class
•private - members cannot be accessed (or viewed)
from outside the class
•protected - members cannot be accessed from outside
the class, however, they can be accessed in inherited
classes
Visibility Modifiers

• When a base class is derived by a derived class with the help


of inheritance, the accessibility of base class by the derived class is
controlled by visibility modes. The derived class doesn’t inherit access
to private data members. However, it does inherit a full parent object,
which contains any private members which that class declares.
• Note: A derived class doesn’t inherit access to private data members.
However, it does inherit a full parent object, which contains any private
members which that class declares.
Example:
1. class ABC : private XYZ //private derivation
{ }
2. class ABC : public XYZ //public derivation
{ }
3. class ABC : protected XYZ //protected derivation
{ }
4. class ABC: XYZ //private derivation by default
{ }
Note:
▪ When a base class is privately inherited by the derived class, public members of the base class becomes the
private members of the derived class and therefore, the public members of the base class can only be
accessed by the member functions of the derived class. They are inaccessible to the objects of the derived
class.
▪ On the other hand, when the base class is publicly inherited by the derived class, public members of the base
class also become the public members of the derived class. Therefore, the public members of the base class
are accessible by the objects of the derived class as well as by the member functions of the derived class.
• Modes of Inheritance:
There are 3 modes of inheritance.
[Link] Mode: If we derive a subclass from a public base class. Then
the public member of the base class will become public in the derived
class and protected members of the base class will become protected
in the derived class.
[Link] Mode: If we derive a subclass from a Protected base class.
Then both public members and protected members of the base class
will become protected in the derived class.
[Link] Mode: If we derive a subclass from a Private base class. Then
both public members and protected members of the base class will
become Private in the derived class.
// C++ Implementation to show that a class B : public A {
// x is public
derived class doesn’t inherit access to // y is protected
private data members. However, it does // z is not accessible from B
};
inherit a full parent object.
class C : protected A {
class A { // x is protected
// y is protected
public: // z is not accessible from C
};
int x;
class D : private A // 'private' is default for classes
protected: {
// x is private
int y; // y is private
// z is not accessible from D
private: };

int z;
};
The below table summarizes the above three modes and shows the access specifier of the members of
the base class in the subclass when derived in public, protected and private modes:
• Types Of Inheritance:-
[Link] inheritance
[Link] inheritance
[Link] inheritance
[Link] inheritance
[Link] inheritance
1. Single Inheritance: In single inheritance, a class is allowed to inherit
from only one class. i.e. one subclass is inherited by one base class only.

• Syntax
class subclass_name : access_mode base_class
{
// body of subclass
};

OR

class A
{
... .. ...
};
class B: public A
{
... .. ...
};
2. Multiple Inheritance: Multiple Inheritance is a feature of C++ where a class can inherit from
more than one class. i.e one subclass is inherited from more than one base class.

Syntax:
class subclass_name : access_mode base_class1, access_mode base_class2, ....
{ // body of subclass };
class B
{
... .. ..
};
class C
{
... .. ...
};
class A: public B, public C
{
... ... ...
};
3. Multilevel Inheritance: In this type of inheritance, a derived class is created
from another derived class.
Syntax:-
class C
{
... .. ...
};
class B:public C
{
... .. ...
};
class A: public B
{
... ... ...
};
4. Hierarchical Inheritance: In this type of inheritance, more than one subclass is
inherited from a single base class. i.e. more than one derived class is created from a
single base class.

Syntax:-
Class G
{ // body of the class G. }
class B : public G
{ // body of class B. }
class E : public G
{ // body of class E. }
class D : public E
{ // body of class D. }
5. Hybrid (Virtual) Inheritance: Hybrid Inheritance is implemented by
combining more than one type of inheritance. For example: Combining
Hierarchical inheritance and Multiple Inheritance.
Polymorphism is supported by C++ both at compile time and at run time. As discussed in
earlier chapters, compile-time polymorphism is achieved by overloading functions and operators.

Run-time polymorphism is accomplished by using inheritance and virtual functions,


Runtime Polymorphism
This type of polymorphism is achieved by Function Overriding. Late binding and dynamic
polymorphism are other names for runtime polymorphism. The function call is resolved at runtime
in runtime polymorphism. In contrast, with compile time polymorphism, the compiler determines
which function call to bind to the object after deducing it at runtime.
Virtual Functions
• A virtual function is a member function that is declared within a base class and redefined by a
derived class.
• To create a virtual function, precede the function's declaration in the base class with the keyword
virtual.
• When a class containing a virtual function is inherited, the derived class redefines the virtual
function to fit its own needs.
• In essence, virtual functions implement the "one interface, multiple methods" philosophy that
underlies polymorphism.
• The virtual function within the base class defines the form of the interface to that function. Each
redefinition of the virtual function by a derived class implements its operation as it relates
specifically to the derived class. That is, the redefinition creates a specific method.
• When accessed "normally," virtual functions behave just like any other type of class member
function. However, what makes virtual functions important and capable of supporting run-time
polymorphism is how they behave when accessed via a pointer.
• a base-class pointer can be used to point to an object of any class derived from that base. When a
base pointer points to a derived object that contains a virtual function, C++ determines which
version of that function to call based upon the type of object pointed to by the pointer.
• And this determination is made at run time. Thus, when different objects are pointed to, different
versions of the virtual function are executed.
• The same effect applies to base-class references.
example : unit4_12.cpp
Calling a Virtual Function Through a Base Class Reference
• A virtual function can be called through a base-class pointer, but the polymorphic nature of a
virtual function is also available when called through a base-class reference.
• Thus, a base-class reference can be used to refer to an object of the base class or any object derived
from that base. When a virtual function is called through a base-class reference, the version of the
function executed is determined by the object being referred to at the time of the call.
• The most common situation in which a virtual function is invoked through a base class reference is
when the reference is a function parameter.
example : unit4_13.cpp
// virtual function
#include <iostream>
using namespace std; int main()
class base { {
public: base *p, b;
virtual void vfunc() { derived1 d1;
cout << "This is base's vfunc().\n";
derived2 d2;
}
// point to base
};
p = &b;
p->vfunc(); // access base's vfunc()
class derived1 : public base {
// point to derived1
public:
p = &d1;
void vfunc() {
p->vfunc(); // access derived1's vfunc()
cout << "This is derived1's vfunc().\n";
// point to derived2
} p = &d2;
}; p->vfunc(); // access derived2's vfunc()
class derived2 : public base { return 0;
public: }
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
};
unit4_12.cpp
Abstract Classes and Methods
• In C++, an abstract class is a class that cannot be instantiated and contains at least one pure virtual
function.
• Because an abstract class contains one or more functions for which there is no definition (that is, a
pure virtual function), no objects of an abstract class may be created. Instead, an abstract class
constitutes an incomplete type that is used as a foundation for derived classes.
• Although you cannot create objects of an abstract class, you can create pointers and references to
an abstract class. This allows abstract classes to support run-time polymorphism, which relies upon
base-class pointers and references to select the proper virtual function.
• A pure virtual function is a virtual function that is declared in the base class but has no
implementation. This means that the derived classes must provide an implementation for the pure
virtual function.
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.

You might also like