CMP1002
Object Oriented Programming
Lecture 5
Function Overloading
and
Operator Overloading
1
Function Overloading
• You overload a function name f by declaring more than one
function with the name f in the same scope
• The declarations of f must differ from each other by the types
and/or the number of arguments in the argument list
2
Function Overloading
• When you call an overloaded function named f, the correct function
is selected by comparing the argument list of the function call with
the parameter list of each of the overloaded candidate functions
with the name f
• A candidate function is a function that can be called based on the
context of the call of the overloaded function name
3
Function Overloading: Example
#include <iostream> int main() {
int a = 8;
using namespace std; print(10);
print(10.10);
void print(int i) { print("ten");
cout << " Here is int " << i << endl; print(a, 7.8);
} }
void print(double f) {
cout << " Here is float " << f << endl; OUTPUT:
} Here is int 10
void print(char* c) { Here is float 10.1
cout << " Here is char* " << c << endl; Here is char* ten
} Here is an int8
Here is a double7.8
void print(int a, double b)
{
cout << " Here is an int" << a << endl;
cout << " Here is a double" << b << endl;
}
4
Function Overloading: Example
• Write a program which computes the volume of the following geometrical
shapes:
1 cube (all sides are equal),
2 cylinder (radius and height)
3 cuboid (length, breadth, height).
5
Restrictions on overloaded functions
• You cannot overload the following function declarations if they
appear in the same scope
1. Function declarations that differ only by return type cannot be
overloaded. For example, you cannot declare the following
declarations:
int f(int a);
float f(int b);
6
Restrictions on overloaded functions
• You cannot overload the following function declarations if they
appear in the same scope
2. Member function declarations that have the same name and the same
parameter types, but one of these declarations is a static member
function declaration
class A{
static int f();
int f();
}
7
Restrictions on overloaded functions
• You cannot overload the following function declarations if they appear in the
same scope
3. Function declarations with parameters that differ only because one is a
pointer and the other is an array. For example, the following are
declarations of the same function:
f(char*);
f(char[10]);
8
Operator Overloading
9
Fundamentals of Operator Overloading
• C++ programming is a type-sensitive and type- focused process.
• Programmers can work with built-in data types, such as integers
and floats, and can also define new types using classes and
structures.
10
Fundamentals of Operator Overloading
• C++ provides a rich collection of operators that can be used to
manipulate these types, including arithmetic operators (+, -, *, /),
comparison operators (==, !=, <, >), and logical operators (&&, ||,
!), among others.
• Operators provide programmers with a concise notation for
expressing manipulations of objects of fundamental types (e.g.
two integers can be added using ‘+’ operator, etc.)
11
Fundamentals of Operator Overloading
• In addition to built-in data types, programmers can use operators with
user-defined types, such as classes and structures.
• While C++ does not allow for the creation of new operators, it does
allow for most existing operators to be overloaded, meaning that their
behavior can be redefined for objects of user-defined types.
• This allows programmers to define the behavior of operators in a way
that is appropriate and meaningful for their objects, providing a
powerful capability for creating intuitive and easy-to-use classes and
structures.
12
Fundamentals of Operator Overloading
• Operator overloading is an important feature of C++ that
contributes to its extensibility, which is one of the language's most
appealing attributes.
• Programmers should use operator overloading when it makes their
code clearer and more concise than accomplishing the same
operations with function calls.
• When overloading operators, programmers should ensure that the
overloaded operators behave in a way that is consistent with their
built-in counterparts. For example, the '+' operator should be
overloaded to perform addition, not subtraction, to avoid
confusion and errors in the code.
13
Operator Overloading
• To overload an operator in C++, programmers can write a non-static
member function definition or a global function definition that defines
the behavior of the operator for a given class or type.
•
When overloading an operator, the function name is replaced with the
keyword 'operator' followed by the symbol for the operator being
overloaded.
•
For example, to overload the addition operator '+', the function name
would be 'operator+' and the definition of this function would specify
how to add two objects of the given class or type.
14
Already Overloaded Operators
• To use an operator on objects of a user-defined class or
type, that operator must be overloaded for that class or
type.
• There are three exceptions to this rule: the assignment
operator (=), the address operator (&), and the comma
operator (,).
• The assignment operator is already used with every class to
perform memberwise assignment of the data members of the
class, so it doesn't need to be overloaded explicitly.
• The address and comma operators may also be used with objects
of any class without overloading.
15
Operator Functions as
Class Members vs.
Global Functions
16
Class Member vs. Global Functions
• Operator functions can be member functions or global functions
• Global functions are often made friends for performance reasons
• Member functions use the this pointer implicitly to obtain one of their class
object arguments (the left operand for binary operators)
• Arguments for both operands of a binary operator must be explicitly
listed in a global function call
17
Operators That Must Be Overloaded as
Member Functions
• When overloading (), [], -> or any of the assignment operators, the operator
overloading function must be declared as a class member
• For the other operators, the operator overloading functions can be class
members or global functions
18
Operators as Member Functions and Global
Functions
• Whether an operator function is implemented as a member function or as a
global function, the operator is still used the same way in expressions. So which
implementation is best?
• When an operator function is implemented as a member function, the leftmost
(or only) operand must be an object (or a reference to an object) of the operator's
class
19
Operators as Member Functions and Global
Functions
• If the left operand must be an object of a different class or a fundamental
type, this operator function must be implemented as a global function
• A global operator function can be made a friend of a class if that function must
access private or protected members of that class directly
20
Overloading Unary Operators
• A unary operator for a class can be overloaded as a non-static
member function with no arguments or as a global function with one
argument; that argument must be either an object of the class or a
reference to an object of the class
21
Overloading Unary Operators
• Example:
class Mystring{ int
length;
public:
bool operator!() const //overloaded ! operator
{
return length == 0;
} // end function operator!
22
Overloading Binary Operators
• A binary operator can be overloaded as a non-static member function with one
argument or as a global function with two arguments (one of those arguments
must be either a class object or a reference to a class object)
23
Overloading Binary Operators
Example: < to compare two String objects class String
{
bool operator<( const String &right ) const
{
return strcmp( sPtr, right.sPtr ) < 0;
} // end function operator<
}; // end class String
24
Example: Complex Number
• Write a complex number function consisting of real and imaginary data
members.
• The function will have a constructor with two parameters. The default values of
the parameters will be set to 0.
• Overload + (plus) operator to add two complex numbers.
25
Example: Complex Number Class with
Overloaded + Operator as a
Member Function
#include <iostream> // define overloaded + (plus) operator
using namespace std; Complex Complex ::operator+ (const Complex & c) const
{
class Complex Complex result;
{ result.real = (real + c.real);
double real, imag;
result.imag = (imag + c.imag);
public:
return result;
Complex( double real = 0., double imag = 0.);
}
Complex operator+(const Complex&) const;
}; int main()
{
// define constructor Complex x(4,4);
Complex :: Complex( double r, double i ) Complex y(6,6);
{ Complex z = x + y; // calls Complex ::operator+()
real = r; imag = i;
} }
26
Example: Complex Number Class with
Overloaded + Operator as a
Global Function
#include <iostream> // define overloaded + (plus) operator as a global function
using namespace std; Complex operator+ (const Complex & c1, const Complex &
c2)
class Complex
{
{
Complex result;
public:
result.real = (c1.real + c2.real); result.imag = (c1.imag +
double real, imag;
c2.imag);
Complex( double real = 0., double imag = 0.); // constructor
return result;
};
}
// define constructor
int main()
Complex :: Complex( double r, double i )
{
{
Complex x(4,4); Complex y(6,6);
real = r; imag = i;
Complex z = x + y; // calls Complex ::operator+()
}
}
27
Already Overloaded Operators
• Address operator (&) returns the address of the object in memory
• Comma operator (,) evaluates the expression to its left then the
expression to its right
28
Operators that can be overloaded
29
Operators that cannot be overloaded
30
Important Notes on Operator
Overloading
• The order of evaluation of operators cannot be changed by overloading.
• Overloaded operators can still be forced to be evaluated in a certain order by
using parentheses.
• The left-to-right or right-to-left associativity of an operator cannot be
changed by overloading.
31
Important Notes on Operator
Overloading
• It is not possible to change the "arity" of an operator (i.e., the number of
operands an operator takes):
• overloaded unary operators remain unary operators
• overloaded binary operators remain binary operators
• C++'s only ternary operator (?:) cannot be overloaded
32
Important Notes on Operator
Overloading
• Operators &, *, + and - all have both unary and binary
versions
• These unary and binary versions can each be overloaded
• Attempting to change the "arity" of an operator via operator
overloading is a compilation error.
33
Creating New Operators
• It is not possible to create new operators; only existing operators can
be overloaded
• Unfortunately, this prevents the programmer from using popular
notations like the ** operator used in some other programming
languages for exponentiation
34
Creating New Operators
• For example, you could overload the ^ operator to perform exponentials it
does in some other languages but it is not allowed to overload ^ by C++
• Attempting to create new operators via operator overloading is a
syntax error.
35
Operators for Fundamental Types
At least one argument of an operator function must be an object or reference
of a user-defined type. This prevents programmers from changing how
operators work on fundamental types.
Attempting to modify how an operator works with objects of fundamental
types is a compilation error.
36
Operators for Fundamental Types
• The meaning of how an operator works on objects of fundamental types
cannot be changed by operator overloading
• The programmer cannot, for example, change the meaning of how + adds two
integers
• 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
37
Related Operators
• Overloading an assignment operator and an addition operator to
allow statements like
object2 = object2 + object1;
does not imply that the += operator is also overloaded to allow
statements such as
object2 += object1;
Such behavior can be achieved only by explicitly overloading
operator += for that class.
38
Friend Function
• What is a Friend Function?
• A friend function is used for accessing the non- public
members of a class.
• A class can allow non-member functions and other classes to access
its own private data, by making them friends.
• Thus, a friend function is an ordinary function or a member of
another class.
39
Example: Overloading ==
and != Operators
class Point
{
private:
double m_dX, m_dY, m_dZ;
public:
Point(double dX=0.0, double dY=0.0, double dZ=0.0) { m_dX = dX; m_dY =
dY; m_dZ = dZ; }
friend bool operator== (Point &cP1, Point &cP2); friend bool operator!=
(Point &cP1, Point &cP2);
double GetX() { return m_dX; } double GetY() {
return m_dY; } double GetZ() { return m_dZ; }
};
50
Example: Overloading ==
and != Operators
bool operator== (Point &cP1, Point &cP2)
{
return (cP1.m_dX == cP2.m_dX && cP1.m_dY
== cP2.m_dY && cP1.m_dZ == cP2.m_dZ);
}
bool operator!= (Point &cP1, Point &cP2)
{
return !(cP1 == cP2); //uses the overloaded ‘==‘ operator
}
41
Overloading cout (<<) operator
Example:
Date dt( 1, 2, 92 );
cout << dt;
To get cout to accept a Date object after the insertion operator, overload the
insertion operator to recognize an ostream object on the left and a Date on
the right.
42
Overloading cout (<<) operator
// overload_date.cpp
#include <iostream>
using namespace std;
class Date
{
int mo, da, yr;
public:
Date(int m, int d, int y)
{
mo = m; da = d; yr = y;
}
friend ostream& operator<<(ostream& os, const Date& dt);
};
43
Overloading cout (<<) operator
ostream& operator<<(ostream& os, const Date& dt)
{
os << dt.mo << '/' << dt.da << '/' << dt.yr; return
os;
}
int main()
{
Date dt(5, 6, 92);
cout << dt;
}
44
Overloading cin (>>) operator
• It is also possible to overload the input operator.
• Very similar to overloading output operator
• The key thing you need to know is that cin is an object of type istream.
45
Overloading cin (>>) operator
istream& operator>> ( istream& is, Date& dt )
{
is >> dt.mo >> dt.da >> dt.yr; return is;
}
46
Thank you
• End of lecture 5