LEC 19-20
Default Function Arguments,
Ambiguity in Function Overloading
and Operator Overloading
Default Function Arguments
• C++ allows a function to assign a parameter a default value when
no argument corresponding to that parameter is specified in a
call to that function.
• For example, this declares myfunc( ) as taking one double
argument with a default value of 0.0:
void myfunc(double d = 0.0)
{
// ...}
myfunc(198.234); // pass an explicit value
myfunc(); // let function use default
The first call passes the value 198.234 to d. The second call
automatically gives d the default value zero.
Ambiguity in Function Overloading
• You can create a situation in which the
compiler is unable to choose between two (or
more) overloaded functions.
• When this happens, the situation is said to be
ambiguous.
• Ambiguous statements are errors, and
programs containing ambiguity will not
compile.
Ambiguity in Function Overloading
int myfunc(double d);
// ...
cout << myfunc('c');
// not an error, conversion applied
• Although automatic type conversions are
convenient, they are also a prime cause of
ambiguity.
Example
#include <iostream>
using namespace std;
float myfunc(float i);
double myfunc(double i);
int main()
{
cout << myfunc(10.1) << " "; // unambiguous, calls
myfunc(double)
cout << myfunc(10); // ambiguous
return 0;
}
Operator Overloading
• In C++, you can overload most operators so
that they perform special operations relative
to classes that you create.
• For example, a class that maintains a stack
might overload + to perform a push operation
and – – to perform a pop.
• When an operator is overloaded, none of its
original meanings are lost. Instead, the type
of objects it can be applied to is expanded.
Operator Overloading
• You overload operators by creating
operator functions.
• An operator function defines the
operations that the overloaded operator
will perform relative to the class upon
which it will work.
• An operator function is created using the
keyword operator.
• Operator functions can be either
members or nonmembers of a class.
• Nonmember operator functions are
almost always friend functions of the
class, however.
Creating a Member Operator Function
ret-type class-name::operator op(arg-list)
{
// operations
}
Unary Operators
• The unary operators operate on a single
operand and following are the examples of
Unary operators −
❑ The increment (++) and decrement (--)
operators.
❑ The unary minus (-) operator.
❑ The logical not (!) operator.
Unary Operator Overload - (using
member function)
#include <iostream>
using namespace std;
class Distance
{
private:
int feet;
int inches;
public:
//constructor
Distance()
{
feet = 0;
inches = 0;
}
//constructor
Distance(int f, int i) {
feet = f;
inches = i;
}
// method to display distance
Contd….
int main()
{
Distance D1(11, 10), D2(-5, 11);
-D1; // apply negation
D1.displayDistance();
// display D1
-D2; // apply negation
D2.displayDistance(); // display D2
return 0;
} Output:
F: -11 I:-10 F: 5 I:-11
Binary Operators
• The binary operators take two arguments.
• You use binary operators very frequently like
addition (+) operator, subtraction (-) operator
and division (/) operator.
• *, ., ::, ?: are operators can not be overloaded.
Overloading Binary Operator (+)
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
//constructors
loc() {
}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator+(loc op2);
};
// Overload + for loc.
Continued…..
int main()
{
loc ob1(10, 20), ob2( 5, 30);
ob1.show(); // displays 10 20
ob2.show(); // displays 5 30
ob1 = ob1 + ob2;
Output:
ob1.show(); // displays 15 50
return 0; 10 20
5 30
}
15 50
Overloading +, -(binary) and ++(unary)
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {} // constructors
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator+(loc op2);
loc operator-(loc op2);
// Overload - for loc.
loc loc::operator-(loc op2)
{
loc temp;
// notice order of operands
temp.longitude = longitude - op2.longitude;
temp.latitude = latitude - op2.latitude;
return temp;
}
// Overload asignment for loc.
loc loc::operator=(loc op2)
{
longitude = op2.longitude;
latitude = op2.latitude;
return *this; // i.e., return object that generated call
}
Output:
// Overload prefix ++ for loc.
10 20
loc loc::operator++()
5 30
{
11 21
longitude++;
12 22
latitude++;
12 22
return *this;
90 90
}
int main()
{
Overloading using Friend Functions
• There are certain situations where we would like to use a
friend function rather than a member function.
• For example if we want to use two different types of a
binary operator, say, one an object and another a built in
type as shown below:
A=B+2 , where A and B are objects of same class. This will
work for a member function, but the statement A=2+B; will
not work.
• This is because the left-handed operand which is
responsible for invoking the membership function should
be an object of the same class.
• Friend function allows both approaches as it is invoked
without the use of objects.
Example
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {} // constructors
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
int main()
{
loc ob1(10, 20), ob2( 5, 30);
ob1 = ob1 + ob2;
ob1.show();
return 0;
} Output:
15 50
Restrictions on application of friend
function
• =, ( ), [ ], or –> operators can not be
overloaded using a friend function.
• When overloading the increment or
decrement operators, you will need to use a
reference parameter when using a friend
function.
Overloading new and delete
// Allocate an object.
void *operator new(size_t size)
{
/* Perform allocation.
Throw bad_alloc on failure.
Constructor called automatically. */
return pointer_to_memory;
}
// Delete an object.
void operator delete(void *p)
{
/* Free memory pointed to by p.
Example
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
void *operator new(size_t size);
void operator delete(void *p);
};
// new overloaded relative to loc.
void *loc::operator new(size_t size)
int main()
{
loc *p1, *p2;
p1 = new loc (10, 20);
p2 = new loc (-10, -20);
}
p1->show();
p2->show();
delete p1;
delete p2;
return 0;
}
Overloading [] operator
• In C++, the [ ] is considered a binary operator when you are
overloading it.
• Therefore, the general form of a member operator[ ]( ) function
is as shown here:
type class-name::operator[](int i)
{
// . . .
}
• Technically, the parameter does not have to be of type int, but an
operator[ ]( ) function is typically used to provide array
subscripting, and as such, an integer value is generally used.
• Given an object called O, the expression O[3] translates into this
call to the operator[ ]( ) function: O.operator[](3)
Example 1
#include <iostream>
using namespace std;
class atype {
int a[3];
public:
atype(int i, int j, int k) {
a[0] = i;
a[1] = j;
a[2] = k;
Output:
} 2
Example 2
class atype {
int a[3];
public:
atype(int i, int j, int k) {
a[0] = i;
a[1] = j;
a[2] = k;
}
int &operator[](int i) {
return a[i];
}
}; Output:
int main() 2 25
{
Overloading ()
• When you overload the ( ) function call operator, you
are not, per se, creating a new way to call a function.
• Rather, you are creating an operator function that can
be passed an arbitrary number of parameters.
Example: double operator()(int a, float f, char *s);
and an object O of its class, then the statement
O(10, 23.34, "hi");
translates into this call to the operator( ) function.
O.operator()(10, 23.34, "hi");
Example
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator+(loc op2);
loc operator()(int i, int j);
};
// Overload ( ) for loc.
loc loc::operator()(int i, int j)
{
longitude = i;
latitude = j;
return *this;
}
// Overload + for loc.
loc loc::operator+(loc op2)
{
Overloading the Comma Operator
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator+(loc op2);
loc operator,(loc op2);
};
// overload comma for loc
loc loc::operator,(loc op2)
{
loc temp;
temp.longitude = op2.longitude;
temp.latitude = op2.latitude;
cout << op2.longitude << " " << op2.latitude << "\n";
return temp;
Overloading ->
• The –> pointer operator, also called the class member
access operator, is considered a unary operator when
overloading.
• Its general usage is shown here:
object->element;
• Here, object is the object that activates the call. The
operator–>( ) function must return a pointer to an object of
the class that operator–>( ) operates upon.
• The element must be some member accessible within the
object.
• The example illustrates overloading the –> by showing the
equivalence between ob.i and ob–>i when operator–>( )
returns the this pointer:
Example
#include <iostream>
using namespace std;
class myclass {
public:
int i;
myclass *operator->()
{
return this;
} Output:
}; 10 10