Sei sulla pagina 1di 31

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> feet = f;
using namespace std; inches = i;
class Distance }
{ // method to display distance
private: void displayDistance() {
int feet; cout << "F: " << feet << " I:" << inches
int inches; <<endl;
public: }
//constructor // overloaded minus (-) operator
Distance()
{ Distance operator- (){
feet = 0; feet = -feet;
inches = 0; inches = -inches;
} return Distance(feet, inches);
//constructor }
Distance(int f, int i) { };
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; loc operator+(loc op2);
class loc { };
int longitude, latitude; // Overload + for loc.
public: loc loc::operator+(loc op2)
//constructors {
loc() { loc temp;
} temp.longitude = op2.longitude +
loc(int lg, int lt) { longitude;
longitude = lg; temp.latitude = op2.latitude + latitude;
latitude = lt; return temp;
} }
void show() {
cout << longitude << " ";
cout << latitude << "\n";
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
10 20
return 0;
5 30
} 15 50
Overloading +, -(binary) and ++(unary)
#include <iostream> loc operator+(loc op2);
using namespace std; loc operator-(loc op2);
class loc { loc operator=(loc op2);
int longitude, latitude; loc operator++();
public: };
loc() {} // constructors // Overload + for loc.
loc(int lg, int lt) { loc loc::operator+(loc op2)
longitude = lg; {
latitude = lt; loc temp;
} temp.longitude = op2.longitude +
void show() { longitude;
cout << longitude << " "; temp.latitude = op2.latitude + latitude;
cout << latitude << "\n"; return temp;
} }
// Overload - for loc. latitude++;
loc loc::operator-(loc op2) return *this;
{ }
loc temp; int main()
// notice order of operands {
temp.longitude = longitude - op2.longitude; loc ob1(10, 20), ob2( 5, 30), ob3(90, 90);
temp.latitude = latitude - op2.latitude; ob1.show();
return temp; ob2.show();
} ++ob1;
// Overload asignment for loc. ob1.show(); // displays 11 21
loc loc::operator=(loc op2) ob2 = ++ob1;
{ ob1.show(); // displays 12 22
longitude = op2.longitude; ob2.show(); // displays 12 22
latitude = op2.latitude; ob1 = ob2 = ob3; // multiple assignment
return *this; // i.e., return object that generated call ob1.show(); // displays 90 90
} ob2.show(); // displays 90 90 Output:
// Overload prefix ++ for loc. return 0; 10 20
loc loc::operator++() } 5 30
{ 11 21
longitude++; 12 22
12 22
90 90
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> friend loc operator+(loc op1, loc op2);
using namespace std; // now a friend
class loc { };
int longitude, latitude; // Now, + is overloaded using friend
public: function.
loc() {} // constructors loc operator+(loc op1, loc op2)
loc(int lg, int lt) { {
longitude = lg; loc temp;
latitude = lt; temp.longitude = op1.longitude +
} op2.longitude;
void show() { temp.latitude = op1.latitude +
op2.latitude;
cout << longitude << " ";
return temp;
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. // Delete an object.
void *operator new(size_t void operator delete(void
size) *p)
{ {
/* Perform allocation. /* Free memory pointed to
Throw bad_alloc on failure. by p.
Constructor called Destructor called
automatically. */ automatically. */
return pointer_to_memory; }
}
Example
#include <iostream> // new overloaded relative to loc.
#include <cstdlib> void *loc::operator new(size_t size)
#include <new>
{
using namespace std;
void *p;
class loc {
cout << "In overloaded new.\n";
int longitude, latitude;
p = malloc(size);
public:
loc() {}
return p;
loc(int lg, int lt) {
}
longitude = lg;
// delete overloaded relative to loc.
latitude = lt;
void loc::operator delete(void *p)
}
{
void show() {
cout << "In overloaded delete.\n";
cout << longitude << " ";
free(p);
cout << latitude << "\n";
}
}
void *operator new(size_t size);
void operator delete(void *p);
};
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> int operator[](int i)
using namespace std; { return a[i];
class atype { }
int a[3]; };
public: int main()
atype(int i, int j, int k) { {
a[0] = i; atype ob(1, 2, 3);
a[1] = j; cout << ob[1]; // displays 2
a[2] = k; return 0; Output:
} } 2
Example 2
class atype { };
int a[3]; int main()
public: {
atype(int i, int j, int k) { atype ob(1, 2, 3);
a[0] = i; cout << ob[1]; // displays 2
a[1] = j; cout << " ";
a[2] = k; ob[1] = 25; // [] on left of =
} cout << ob[1]; // now displays
int &operator[](int i) { 25
return a[i]; return 0;
} }
Output:
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; // Overload + for loc.
class loc { loc loc::operator+(loc op2)
int longitude, latitude; {
public: loc temp;
loc() {} temp.longitude = op2.longitude + longitude;
loc(int lg, int lt) { temp.latitude = op2.latitude + latitude;
longitude = lg; return temp;
latitude = lt; }
}
void show() {
cout << longitude << " "; int main()
cout << latitude << "\n"; {
} loc ob1(10, 20), ob2(1, 1);
loc operator+(loc op2); ob1.show();
loc operator()(int i, int j); ob1(7, 8); // can be executed by itself
}; ob1.show();
// Overload ( ) for loc. ob1 = ob2 + ob1(10, 10); // can be used in expressions
loc loc::operator()(int i, int j) ob1.show();
{ return 0;
longitude = i; }
latitude = j;
return *this;
Overloading the Comma Operator
#include <iostream> cout << op2.longitude << " " << op2.latitude << "\n";
using namespace std; return temp;
class loc { }
int longitude, latitude; // Overload + for loc
public: loc loc::operator+(loc op2)
loc() {} {
loc(int lg, int lt) { loc temp;
longitude = lg; temp.longitude = op2.longitude + longitude;
latitude = lt; temp.latitude = op2.latitude + latitude;
} return temp;
void show() { }
cout << longitude << " "; int main()
cout << latitude << "\n"; {
} loc ob1(10, 20), ob2( 5, 30), ob3(1, 1);
loc operator+(loc op2); ob1.show();
loc operator,(loc op2); ob2.show();
}; ob3.show();
// overload comma for loc cout << "\n";
loc loc::operator,(loc op2) ob1 = (ob1, ob2+ob2, ob3);
{ ob1.show(); // displays 1 1, the value of ob3
loc temp; return 0;
temp.longitude = op2.longitude; }
temp.latitude = op2.latitude;
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; int main()
class myclass { {
public: myclass ob;
int i; ob->i = 10;
myclass *operator->() // same as ob.i
{ cout << ob.i << " " << ob->i;
return this; return 0;
} } Output:
10 10

Potrebbero piacerti anche