0% found this document useful (0 votes)
6 views49 pages

Chapter 7

The document discusses operator overloading in C++, detailing how almost all operators can be redefined with new meanings, while noting limitations such as the inability to overload operators for primitive data types. It covers various aspects of operator overloading, including defining operators as functions or member functions, the handling of binary and unary operators, and the importance of managing assignment operators and implicit functions. Additionally, it highlights specific operators like increment, decrement, and the comma operator, and emphasizes the need for careful implementation to avoid ambiguity and ensure proper functionality.

Uploaded by

sudhaviju1
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views49 pages

Chapter 7

The document discusses operator overloading in C++, detailing how almost all operators can be redefined with new meanings, while noting limitations such as the inability to overload operators for primitive data types. It covers various aspects of operator overloading, including defining operators as functions or member functions, the handling of binary and unary operators, and the importance of managing assignment operators and implicit functions. Additionally, it highlights specific operators like increment, decrement, and the comma operator, and emphasizes the need for careful implementation to avoid ambiguity and ensure proper functionality.

Uploaded by

sudhaviju1
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd

Module 3

Ch 2. Operator Overloading
Introduction
Almost all operators in C++ can be
overloaded with new meanings.
Operators may not look like functions but
can hide function invocations.
You cannot overload the meaning of
operators if all arguments are primitive data
types, nor can you change the precedence or
associativity of operators.

Ch 7. Operator Overloading 2
Figure 7.1 Overloadable Operators
in C++
+ - * / %
^ & | ~ ! &&
|| ++ -- << >> ,
< <= == != > >=
= += -= *= /= %=
&= |= ^= <<= >>=
[] () -> new delete

Ch 7. Operator Overloading 3
Overloaded Functions or
Methods
Operators can be defined either as functions or as
member functions.
How to decide which option is preferable
An ordinary function is normally not permitted access
to the private portions of the class, whereas a member
function is allowed such access.
Implicit conversions will be performed for both right
and left arguments if the operator is defined in
functional form, but only for the right argument if the
operator is defined as a member function.

Ch 7. Operator Overloading 4
Figure 7.2 Comparison Defined as
an Ordinary Function
class box {
public:
box (int v) : value(v) { }
int value;
};

// define meaning of comparison for boxes


bool operator < (box & left, box & right) {
return [Link] < [Link];
}

Ch 7. Operator Overloading 5
Figure 7.3 Comparison Defined as
a Member Function
class box {
public:
box (int v) : value(v) { }

// define meaning of comparison for boxes


bool operator < (box & right)
{ return value < [Link]; }

private:
int value;
};

Ch 7. Operator Overloading 6
Simple Binary Operators
const rational operator
+ (const rational & left, const rational & right)
{
// return sum of two rational numbers
rational result (
[Link]() * [Link]() +
[Link]() * [Link](),
[Link]() * [Link]());
return result;
}

Ch 7. Operator Overloading 7
Simple Binary Operators
Unary operations are either defined as a no-
argument ordinary function or as a no-argument
member function.
Always return a constant value, unless you want
the result to be a target for an assignment.

rational a(2,3), b(7,8);


(a + b) = b;
// error: constant result cannot be reassigned

Ch 7. Operator Overloading 8
The Comparison Operators
bool operator < (const rational & left, const rational & right)
{
// less than comparison of two rational numbers
return [Link]() * [Link]() <
[Link]() * [Link]();
}

// define greater than in terms of less than


template <class T>
bool operator > (T & left, T & right)
{ return right < left; }

Ch 7. Operator Overloading 9
The Increment and Decrement
Operators
If the increment operator is overloaded, you
should define both the prefix and postfix
forms.
Whenever you have a choice, always
invoke the prefix form of the increment
operator as it is usually simpler.

Ch 7. Operator Overloading 10
class box {
public:
box (int v) : value(v) { }

// prefix versions, ++aBox


int operator ++ () { value++; return value; }
int operator -- () { value--; return value; }

int operator ++ (int) // postfix versions aBox++


{
int result = value; // step 1, save old value
value++; // step 2, update value
return result; // step 3, return original
}
int operator -- (int) {
int result = value;
value--;
return result;
}
private:
int value;
};

Ch 7. Operator Overloading 11
class box {
public:
...
const box & operator ++ () { value++; return *this; }
}

box mybox(3);
mybox++++; // error - cannot increment constant value
mybox+++= 7; // error - cannot assign to constant value
mybox++ = 7; // error - cannot assign to constant value

Ch 7. Operator Overloading 12
Avoid expressions whose meanings are not
completely clear.

int i = 5;
int x = i + ++i;
// ambiguous result

Ch 7. Operator Overloading 13
The Shift Operators
The shift operators are overloaded in exactly
the same fashion as the binary arithmetic
operators.

cout << "m " << m << " n " << n << " average " << (n+m)/2.0 << '\n';

Ch 7. Operator Overloading 14
ostream & operator <<
(ostream & out, const rational & value)
{
// print representation of rational number on an output stream
out << [Link]() << '/' << [Link]();
return out;
}

Avoid the right shift of signed integer values.

Ch 7. Operator Overloading 15
The Assignment Operator
The assignment, comma, and address-of operators
will be constructors will be constructed automatically
if the programmer does not specify an alternative.
class box {
public:
box () { value = 0; }
box (int i) { value = i; }
int value;
};
box a(7);
box b;
b = a;

Ch 7. Operator Overloading 16
Always redefine the assignment operator in classes
that include a pointer value.

const box & operator = (box & left, const box & right) {
[Link] = [Link];
return left;
}

const box & operator = (box & left, int right) {


[Link] = right;
return left;
}

box c;
c = a;
b = 2 + (a = 3);
Ch 7. Operator Overloading 17
Always check for self-assignment.

a = a; // make certain this works

const string string::operator = (const string & right)


{
if (this == right) // check for self assignment
return right;
...
}

Ch 7. Operator Overloading 18
Despite the use of the assignment symbol,
constructors do not use the assignment
operator.

box d = c; // uses copy constructor

If addition and assignment are both


overloaded, then += should be overloaded
as well.
Ch 7. Operator Overloading 19
class bigbox : public box {
public:
bigbox (int i, double d) : box(i), dvalue(d) { }
void operator = (bigbox & right) {
value = [Link];
dvalue = [Link];
}
protected:
double dvalue;
};

box a(3);
bigbox b(3, 4.0);

a = b; // legal, but sliced, box assignment,


b = a; // not legal, argument must be a bigbox

Ch 7. Operator Overloading 20
The Compound Assignment
Operators
Whenever possible, define one operator in terms of another.

AnObject operator + (const AnObject & left, const AnObject & right) {
AnObject clone(left); // copy the left argument
clone += right; // combine with right
return clone; // return updated value
}

const AnObject & operator += (AnObject & left, const AnObject & right) {
AnObject sum = left + right;
left = sum;
return left;
}

Ch 7. Operator Overloading 21
The Subscript Operator
Subscript operator is often defined for classes that
represent a container abstraction.

class safeArray {
public:
safeArray (int s) { size = s; values = new int[size]; }
int & operator [ ] (unsigned int i) {
assert(i < size);
return values[i];
}
private:
unsigned int size;
int * values;
};

Ch 7. Operator Overloading 22
The real vector data type does not check
subscript ranges.
safeArray v(10);
v[2] = 7;
v[3] = v[2] + 12;

When returning a referenc, make sure that


the value will continue to exist after the
function exists.
Ch 7. Operator Overloading 23
The Parenthesis Operator
Function Object: an object that can be used as
though it were a function.

class LargerThan {
public:
// constructor
LargerThan (int v) { val = v; }

// the function call operator


bool operator () (int test)
{ return test > val; }
private:
int val;
};
Ch 7. Operator Overloading 24
LargerThan tester(12);

int i = ... ;

if (tester(i)) // true if i is larger than 12

A temporary object can be created by simply


naming the class and any arguments to the
constructor.

list<int>::iterator found =
find_if ([Link](), [Link](), LargerThan(12));

Ch 7. Operator Overloading 25
The Address-of Operator
Rate to use, but when it yields a value of type void
produces a class of objects that cannot have their
address computed, it is useful.
class box {
public:
box () { i = 7; }
private:
int i;
};

box a;
box * b; // b is a pointer to a box
b = & a; // b now points to a
Ch 7. Operator Overloading 26
The Logical Connectives
Short-circuit evaluation means that in some
situations only the left argument is
evaluated, and the right argument is not
even examined.
There is no way to overload the logical
operators and preserve the short-circuit
evaluation.

Ch 7. Operator Overloading 27
The Comma Operator
The for statements in Java and C++ use the
same syntax and achieve a similar result but
use different mechanisms.

int i, j;
for (i = 0, j = 1; x[i] != 0; i++)
if (x[i] == x[j]) j++;

Ch 7. Operator Overloading 28
Mistakenly taping a comma instead of a
period can be a very subtle programming
error.

x = 7,12;

class box {

template <class T>


const T & operator , (T & right) { return right; }

};

Ch 7. Operator Overloading 29
An overloaded comma operator can never have
the same short-circuit semantics as the original.

class box {
public:
box (int v) : val(v) { }
int value () { return val; }

int operator , (box & right)


{ return [Link](); }

private:
int val;
};
Ch 7. Operator Overloading 30
The Arrow Operator
Overloading arrow operator is useful in creating
objects that have a ‘pointer-like’ behavior.
The arrow operator can be defined only as a
member function, and the return type must either
be a pointer to a class type or an object for which
the member access arrow is itself defined.
A smart pointer is an object that can be used in
the manner of a pointer.

Ch 7. Operator Overloading 31
Example of Arrow Operator
class countPointer {
public:
countPointer(Window * w)
{ count = 0; win = w; }
Window * operator->()
{ count++; return win; }
private:
Window * win;
int count;
};

Window * x = new Window(...); // create the underlying value


countPointer p(x); // create a counting pointer value
p->setSize(300, 400); // invoke method in class window
Ch 7. Operator Overloading 32
Conversion Operators
Conversions from user types are defined by
conversion operators; conversions to user types are
defined by using constructors.

operator double (const rational & val) {


return [Link]() / (double)
[Link]();
}

rational r (2, 3);


double d;
d = 3.14 * double(r); // cast converts fraction to double
Ch 7. Operator Overloading 33
Example of Conversion Operators
class rational {
...
operator double () const
{ return numerator() / (double) denominator(); }
...
};

Ch 7. Operator Overloading 34
Memory management Operators
It is possible to overload the memory management
operators new and delete, obtaining even more
control over these tasks than is provided by the
default implementations.

Ch 7. Operator Overloading 35
Disallowing Operators
An operator declared as private can be used only
within a class definition.
class box {
public:
box (int v) : val(v) { }
int value () { return val; }
private:
void operator = (box & right) { }
}

box aBox (2); // create a new box


box bBox (3); // and another

aBox = bBox; // error -- assignment is private


Ch 7. Operator Overloading 36
Implicit Functions and
Invocations
Implicit function definitions and implicit function
invocations are invoked without the programmer
directly requesting it.

Ch 7. Operator Overloading 37
Implicitly Created Operations
The default construct, copy constructor, destructor,
assignment operator, address operator, and comma
operator will all be given implicit meanings unless
overridden by the programmer.
class emptyBox : public box {
private:
box aField;
};

Ch 7. Operator Overloading 38
class emptyBox : public box {
public: // constructors
emptyBox () : box() , aField() { }
emptyBox (const emptyBox & right)
: box(right), aField([Link]) { }
~emptyBox() // destructor {
// implicit deletion of aField
// implicit call on parent class destructor
}
const emptyBox & operator = (const emptyBox & right) {// operators
aField = [Link];
box::operator = (right);
return *this;
}
emptyBox * operator & () { return * this; }
template <class T>
const T & operator , (const T & right) { return right; }
private:
box aField;
};
Ch 7. Operator Overloading 39
Implicit Constructors
If no constructor are specified, an implicit
default constructor constructor will be created.
First, invoke the default constructor for the
parent class if the current class was formed by
using inheritance.
The function will recursively apply default
initialization rules for every data field.
An implicit copy constructor is created if no
other copy constructor is specified, even if
other constructors have been defined.

Ch 7. Operator Overloading 40
Implicit Destructors
First, invoke destructors for every data field
and then invoke the destructor for the parent
class.
Fields are destroyed in the opposite order listed
in the class body.
An implicit destructors is never considered
virtual.

Ch 7. Operator Overloading 41
Implicit Assignment Operator
Created implicitly, takes as an argument a value
of the same type as the class and recursively
assigns each data field from the corresponding
fields in the argument object.
If there is parent class, the assignment operator
for the parent class is then invoked.

Ch 7. Operator Overloading 42
Implicit Address and Comma
The implicit address simply returns a reference
to the current object.
The implicit comma operator simply returns a
reference to the argument object.

Ch 7. Operator Overloading 43
Implicit Function Invocations
Implicit function invocation can greatly
increase a program’s execution time.
A copy constructor always invoked to pass
a by-value object.

Ch 7. Operator Overloading 44
class box {
public:
box () { value = 0; }
box (int i) { value = i; }
box (box & a) { value = [Link]; }

~box() { } // destructor

void operator = (box & right) { value = [Link];}


operator int () { return value; }

private:
int value;
};

box operator + (box & left, box & right) {


return box(((int) left) + (int) right);
}
Ch 7. Operator Overloading 45
int foo (box abox)
{
box bbox;
bbox = abox + 1;
return bbox;
}

int main()
{
box mybox(3);
mybox = 4;
mybox = foo (mybox + 1);
return 0;
}
Ch 7. Operator Overloading 46
box mybox(3);
// integer constructor
mybox = 4;
// integer constructor to create temporary
// assignment of temporary to variable
// destructor on temporary
mybox = foo (mybox + 1); // start of statement
// integer constructor to create temporary
// binary addition of boxes
box operator + (box & left, box & right)
return box(((int) left) + (int) right); // inside addition operator
// conversion of left box to integer
// conversion of right box to integer
// integer constructor for temporary
// return from addition operator
mybox = foo (mybox + 1); // continuation of statement
box bbox; // inside function foo
// default constructor to create variable

Ch 7. Operator Overloading 47
bbox = abox + 1; // start execution
// integer constructor to create temporary for constant
// binary addition operator for boxes
box operator + (box & left, box & right)
return box(((int) left) + (int) right); // inside addition operator
// conversion of left box to integer
// conversion of right box to integer
// integer constructor for temporary
bbox = abox + 1; // continue execution
// assignment for boxes
// destructor for temporary
// conversion from box to integer
// destructor for local variable bbox
// return from function
// destructor for temporary argument
mybox = foo (mybox + 1); // continuation of statement
// integer constructor converting result to box
// assignment operation
// destructor of temporary value
// destructor of variable mybox

Ch 7. Operator Overloading 48
class string {
public: // constructors
string (char * c) ...
string (const string & s) ...
string (int i) ...
};

string aString = 'a';

class string {
public: // constructors
string (char * c) ...
string (const string & s) ...
explicit string (int i) ...
};
Ch 7. Operator Overloading 49

You might also like