Operator Overloading in C++

Download as pdf or txt
Download as pdf or txt
You are on page 1of 21

Operator Overloading in C++

Compile-time Polymorphism

Dr. K. Veningston
Department of Computer Science and Engineering
National Institute of Technology Srinagar
[email protected]
Quick Recap
• Encapsulation
– Encapsulation binds the data & functions together into one single unit (class),
which keeps both safe from outside interference.
• Data encapsulation leads to data hiding.
– Data hiding is a concept in OOP which confirms the security of members of a
class from unauthorized access
– Data hiding using access specifiers (public, private, protected) from outside
world.
• Data hiding is a technique of protecting the data members from being manipulated or hacked
from any other source.
– Data hiding also reduces some complexity of the system.
• Data hiding can be achieved through the encapsulation, as encapsulation is a subprocess of
data hiding.
• Data hiding guarantees restricted data access to class member & maintain object integrity.
Quick Recap
• Abstraction
– Abstraction is primarily used to hide the complexity.
– It indicates the necessary characteristics of an object that differentiates it
from all other types of objects.
– An abstraction concentrates on the external aspect of an object.
• For an object, abstraction provides the separation of the crucial behaviour from its
implementation.
– A proper abstraction emphasizes on the details that are important for the
reader or user and suppresses features that are irrelevant and deviant.
– Every real-world entity has a certain level of abstraction.
• Hiding the details of a particular method.
• Example: Laptop functionalities
Quick Recap
• Data hiding vs. Encapsulation vs. Abstraction
Basis Data hiding Encapsulation Abstraction
Definition Hides the data from the Encapsulation concerns Extracts only relevant
parts of the program about wrapping data to information and ignore
hide the complexity of a inessential details
system

Purpose Restricting or permitting Enveloping or wrapping Hide the complexity


the use of data inside the the complex data
capsule
Access specifier The data under data hiding The data under -
is always private and encapsulation may be
inaccessible. private or public or
protected.
Polymorphism
• Polymorphism means having many forms.
– We can define polymorphism as the ability of a function to take more
than one form.
• In C++, polymorphism is mainly divided into 2 types
– Compile time polymorphism (static binding)
– Runtime polymorphism (dynamic binding)
Compile time polymorphism
• This type of polymorphism is achieved by function overloading
and operator overloading.
– Overloading helps us exploit the concept of polymorphism.
• Function overloading
– Same name for defining different functionalities
• Operator overloading
– Same operator for defining different operations.
Run-time polymorphism
• Runtime polymorphism is a.k.a. dynamic polymorphism or late
binding.
– In runtime polymorphism, the function call is resolved at runtime.
• In contrast, to compile time or static polymorphism, the
compiler deduces the object at runtime and then decides
which function call to bind to the object.
– This type of polymorphism is achieved by function overriding.
• Function overriding occurs when a derived class has a definition for one of the
member functions of the base class. That base class function is said to be
overridden.
Polymorphism
• 2 types of polymorphism (this feature is exclusive to C++, not
for other languages like python [interpreted language])
– Compile-time polymorphism
• Compiler knows at compile-time ‘what a particular token [i.e. function name/
operator name] means’ in the context.
• Achieved using function overloading or operator overloading.
– Run-time polymorphism
• Compiler does not know at compile-time ‘what a particular token [i.e.]
means’
• At run-time, it gets resolved for the compiler. To be
• Achieved using virtual classes/virtual functions or function overriding. covered
Operator Overloading
• In C++, we can change the way operators work for user-defined
types like objects and structures. This is known as operator
overloading.
• Examples:
– An operator can have different meanings depending on the context
where this operator is used.
• 10 + 20 → Addition For the in-built/default datatypes (int, string), it is
• “Hello” + “World!” → Concatenation already implemented ‘what the operator’ means.
Operator Overloading
• a+b does not mean anything valid. struct A {

• It will give an error if we do not overload + …
operator for this structure A. };
int main(){
– We have to overload the + operator for this struct A a, b;
statement a+b to be meaningful. cout<<a+b;
• Same thing goes with class as well. }
How to implement operator overloading?
• Syntax:
– To overload an operator, we use a special operator function
class className {
public:
returnType operator symbol (arguments) {


}
};
How to implement operator overloading?
• Example:
Complex operator + (…) {
Complex temp;


return temp;
}

• Note:
– All the operators in C++ can be overloaded except 4 operators.
• ?:, sizeof, ::, .
Operator overloading in Unary operators
• Unary operators
Pre-increment
operate on only one
operand.
– The increment
operator ++ and
decrement operator
-- are examples of
unary operators. Post-increment
Operator overloading in Binary operators
• Binary operators work on two operands
class Complex{ int main(){
public: Complex c1, c2;
int r, i; Complex c3 = c1+c2;
Complex operator + (const Complex& c) { //c3 = c1.operator+(c2);
Complex temp; return 0;
temp.r = r + c.r; }
temp.i = i + c.i;
return temp;
}
}
Operator overloading
• Two operators = and & are already overloaded by default in C++.
– For example, to copy objects of the same class, we can directly use the = operator i.e.
default copying. We do not need to create an operator function.
– &obj means address of obj→ & is overloaded for class, structure, union.
• We can overload &, but it is not a good practice.
• Operator overloading cannot change the precedence and associativity of
operators.
– Example:
• obj1 + ++obj2 – obj1 * obj2 / obj1;
• ((obj1 + (++obj2)) – obj1) * obj2 / obj1;
• There are 4 operators that cannot be overloaded in C++.
– :: (scope resolution operator)
– . (member selection) and .* (member selection through pointer to function)
– sizeof operator
– ?: (ternary operator)
Different approaches to Operator overloading
• We can perform operator overloading by implementing any of the
following types of functions.
– Member function (we have seen this so far)
• c3 = c1 + c2; → c3 = c1.operator + (c2);
• The operator overloading function may be a member function when a left operand is
an object of the class.
– Non-member function
• Complex operator + (const Complex &c1, const Complex &c2){…}
• When the left operand is different, the operator overloading function should be a
non-member function.
– Friend function
• We can make the operator overloading function a friend function if it needs to access
the private and protected class members.
Restrictions to Operator overloading
• The operators :: (scope resolution), . (member access), .* (member access
through pointer to member), and ?: (ternary conditional) cannot be overloaded.
• New operators (non-operators) such as **, <>, or &| cannot be created.
– Only existing operators can be overloaded.
• It is not possible to change the precedence, grouping, or number of operands of
operators.
• The overload of operator -> must either return a raw pointer, or return an object
(by reference or by value) for which operator -> is in turn overloaded.
– *ptr = &obj; → (*ptr).i <-> a.i <-> ptr -> i
– Whenever we overload this operator ->, it must return an address to some data member
of the class.
• The overloads of operators && and || lose short-circuit evaluation.
Function call operator
• When a user-defined class overloads the function call operator
i.e. (), it becomes a FunctionObject type.
– An object of such a type can be used in a function call like expression.

struct Linear{ int main(){


double a, b; Linear f{2, 1};
Linear g{-1, 0};
double operator () (double x) const { double f_0 = f(0);
return a * x + b; double f_1 = f(1);
} double g_0 = g(0);
} return 0;
}
#include<iostream>
Exercise 1
using namespace std;
class A{
int a, b;
public:
A(int x, int y) {
a =x; b=y;
}
A operator+(A const &obj){
A temp(0,0);
temp.a = a + obj.a;
temp.b = b + obj.b;
return temp;
}
void print (){
cout<<a<<b<<endl;
}
};
int main(){
A obj1(2, 6), obj2(1, 8);
A obj3 = obj1+obj2;
obj3.print();
}
#include<iostream>
using namespace std; Exercise 2
class A{
int a, b;
public:
A(int x, int y){
a =x; b=y;
}
void operator+(A const &obj){
a += obj.a;
b += obj.b;
}
void print(){
cout<<a<<b<<endl;
}
};
int main(){
A obj1(2, 6), obj2(1, 8);
obj1+obj2;
obj1.print();
obj2.print();
}

You might also like