Top Banner
Ch 7. Operator Overloading Timothy Budd
49

Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Dec 26, 2015

Download

Documents

Jessie Powell
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading

Timothy Budd

Page 2: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 2

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.

Page 3: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 3

Figure 7.1 Overloadable Operators in C++

+ - * / %

^ & | ~ ! &&

|| ++ -- << >> ,

< <= == != > >=

= += -= *= /= %=

&= |= ^= <<= >>=

[] () -> new delete

Page 4: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 4

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.

Page 5: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 5

Figure 7.2 Comparison Defined as an Ordinary Function

class box {public:

box (int v) : value(v) { }int value;

};

// define meaning of comparison for boxesbool operator < (box & left, box & right) {

return left.value < right.value; }

Page 6: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 6

Figure 7.3 Comparison Defined as a Member Function

class box {public:

box (int v) : value(v) { }

// define meaning of comparison for boxesbool operator < (box & right)

{ return value < right.value; }

private:int value;

};

Page 7: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 7

Simple Binary Operators

const rational operator

+ (const rational & left, const rational & right)

{// return sum of two rational numbersrational result (

left.numerator() * right.denominator() + right.numerator() * left.denominator(),

left.denominator() * right.denominator());return result;

}

Page 8: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 8

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

Page 9: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 9

The Comparison Operatorsbool operator < (const rational & left, const rational & right)

{// less than comparison of two rational numbersreturn left.numerator() * right.denominator() <

right.numerator() * left.denominator();

}

// define greater than in terms of less than

template <class T>

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

Page 10: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 10

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.

Page 11: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 11

class box {public:

box (int v) : value(v) { }

// prefix versions, ++aBoxint operator ++ () { value++; return value; }int operator -- () { value--; return value; }

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

int result = value; // step 1, save old valuevalue++; // step 2, update valuereturn result; // step 3, return original

}int operator -- (int) {

int result = value;value--;return result;

}private:

int value;};

Page 12: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 12

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

Page 13: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 13

Avoid expressions whose meanings are not completely clear.

int i = 5;int x = i + ++i;

// ambiguous result

Page 14: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 14

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';

Page 15: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 15

ostream & operator <<

(ostream & out, const rational & value)

{// print representation of rational number on an output streamout << value.numerator() << '/' << value.denominator();return out;

}

Avoid the right shift of signed integer values.

Page 16: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 16

The Assignment OperatorThe 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;

Page 17: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 17

Always redefine the assignment operator in classes that include a pointer value.

const box & operator = (box & left, const box & right) {left.value = right.value;return left;

}

const box & operator = (box & left, int right) {left.value = right;return left;

}

box c;c = a;b = 2 + (a = 3);

Page 18: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 18

Always check for self-assignment.

a = a; // make certain this works

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

if (this == right) // check for self assignmentreturn right;

...}

Page 19: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 19

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.

Page 20: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 20

class bigbox : public box {public:

bigbox (int i, double d) : box(i), dvalue(d) { }void operator = (bigbox & right) {

value = right.value;dvalue = right.dvalue;}

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

Page 21: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 21

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 argumentclone += right; // combine with rightreturn clone; // return updated value

}

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

}

Page 22: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 22

The Subscript OperatorSubscript 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;

};

Page 23: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 23

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.

Page 24: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 24

The Parenthesis OperatorFunction Object: an object that can be used as though it were a function.

class LargerThan {public:

// constructorLargerThan (int v) { val = v; }

// the function call operatorbool operator () (int test)

{ return test > val; }private:

int val;};

Page 25: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 25

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 (aList.begin(), aList.end(), LargerThan(12));

Page 26: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 26

The Address-of OperatorRate 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 boxb = & a; // b now points to a

Page 27: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 27

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.

Page 28: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 28

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++;

Page 29: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 29

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; }

};

Page 30: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 30

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 right.value(); }

private:int val;

};

Page 31: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 31

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.

Page 32: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 32

Example of Arrow Operatorclass 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 valuecountPointer p(x); // create a counting pointer valuep->setSize(300, 400); // invoke method in class window

Page 33: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 33

Conversion OperatorsConversions from user types are defined by conversion operators; conversions to user types are defined by using constructors.

operator double (const rational & val) {return val.numerator() / (double)

val.denominator();}

rational r (2, 3); double d;d = 3.14 * double(r); // cast converts fraction to double

Page 34: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 34

Example of Conversion Operators

class rational {...

operator double () const{ return numerator() / (double) denominator(); }

...

};

Page 35: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 35

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.

Page 36: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 36

Disallowing OperatorsAn 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 boxbox bBox (3); // and another

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

Page 37: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 37

Implicit Functions and Invocations

Implicit function definitions and implicit function invocations are invoked without the programmer directly requesting it.

Page 38: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 38

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;

};

Page 39: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 39

class emptyBox : public box {public: // constructors

emptyBox () : box() , aField() { }emptyBox (const emptyBox & right)

: box(right), aField(right.aField) { }

~emptyBox() // destructor {// implicit deletion of aField// implicit call on parent class destructor}const emptyBox & operator = (const emptyBox & right) {// operatorsaField = right.aField;box::operator = (right);return *this;}emptyBox * operator & () { return * this; }template <class T>const T & operator , (const T & right) { return right; }

private:box aField;

};

Page 40: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 40

Implicit ConstructorsIf 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.

Page 41: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 41

Implicit DestructorsFirst, 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.

Page 42: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 42

Implicit Assignment OperatorCreated 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.

Page 43: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 43

Implicit Address and CommaThe implicit address simply returns a reference to the current object.

The implicit comma operator simply returns a reference to the argument object.

Page 44: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 44

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.

Page 45: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 45

class box {public:

box () { value = 0; }box (int i) { value = i; }box (box & a) { value = a.value; }

~box() { } // destructor

void operator = (box & right) { value = right.value;}operator int () { return value; }

private:int value;

};

box operator + (box & left, box & right) {return box(((int) left) + (int) right);

}

Page 46: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 46

int foo (box abox)

{box bbox;bbox = abox + 1;return bbox;

}

int main()

{box mybox(3);mybox = 4;mybox = foo (mybox + 1);return 0;

}

Page 47: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 47

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 statementbox bbox; // inside function foo

// default constructor to create variable

Page 48: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 48

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

Page 49: Ch 7. Operator Overloading Timothy Budd. Ch 7. Operator Overloading2 Introduction Almost all operators in C++ can be overloaded with new meanings. Operators.

Ch 7. Operator Overloading 49

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) ...

};