21
OPERATOR OVERLOADING Michael Heron

2CPP13 - Operator Overloading

Embed Size (px)

DESCRIPTION

This is an intermediate conversion course for C++, suitable for second year computing students who may have learned Java or another language in first year.

Citation preview

Page 1: 2CPP13 - Operator Overloading

OPERATOR OVERLOADINGMichael Heron

Page 2: 2CPP13 - Operator Overloading

Introduction• Today’s lecture is about operator overloading.• Here be dragons.

• This is not a facility of which I am very fond…• … coverage in the module is provided for completeness.

• It is a facility that does not exist in Java or C#.• It is very powerful, very useful, but one of the easiest

ways to develop virtually unreadable code.

Page 3: 2CPP13 - Operator Overloading

Operator Overloading• Operator overloading is the process of providing object

specific functionality for the base operators:• +• -• /• *

• You can overload these to allow you to, for example, divide objects by each other or multiply them together.• In Java if you wish to do this, you must define methods for the

operation.

Page 4: 2CPP13 - Operator Overloading

The Structure of an Operator• All operators, fundamentally, do two things:

• Operate on one or more values (known as operands)• Return a value

• Consider the example:• int num = 4 + 5• Operator is +• Operands and 4 and 5• Returns the sum of the two operands - 9

Page 5: 2CPP13 - Operator Overloading

Overloading an Operator• In C++, an overloaded operator is just another method

defined in the class.• As with a constructor, it has a specific naming convention.

• The method name is the keyword operator followed by the operator symbol:• operator+, as an example.

• These must be prototyped as usual in the class definition.

Page 6: 2CPP13 - Operator Overloading

Overloaded Operatorclass Employee {private: int payscale;public: int query_payscale(); void set_payscale (int p); virtual bool can_hire_and_fire(); virtual bool has_authority (string); int operator+ (int);}

int Employee::operator+ (int num) { payscale += num; return payscale;}

Page 7: 2CPP13 - Operator Overloading

Limitations• Overloaded operators will not work with pointers.

• They work only with value objects.• If you want to use an overloaded operator on a pointer, you must

explicitly dereference it first.

• You can only redefine pointers for classes you write yourself.

• The left hand operand is always the left hand side of the operator.

• The right hand side can be any data type.

Page 8: 2CPP13 - Operator Overloading

Applicability• Almost any operator can be overloaded in C++.

• Including array notation and the new keyword.

• In most cases, the overloaded operators are just for convenience.• A syntactic nicety.

• Which comes with all sorts of problems.

• However, it is often necessary to overload the = operator.

Page 9: 2CPP13 - Operator Overloading

Dynamic Data• C++ allows us to pass by both reference and value.

• For objects and primitive data types.

• Java allows only pass by reference.• What happens in C++ if we pass by value an object

containing pointers?• It creates only a shallow copy of the object.• It copies only the object’s data fields.

• The pointer in the copy will point to the original dynamic memory.

Page 10: 2CPP13 - Operator Overloading

Shallow Copies• This is known as a shallow copy:

• Person a;• Person b = a;• Both a and b make use of the same dynamic data.

• C++ gives us two ways of dealing with this.• Overloading the assignment operator• Defining a copy constructor.

• They have the same basic intention.• Assignment operators are used when an object already exists.• Copy constructors are used when a new object must be created.

Page 11: 2CPP13 - Operator Overloading

Copy Constructors• There’s nothing syntactically special about a copy

constructor.• It’s a constructor that takes a configured object as a parameter.• This object must be passed by reference

• Where it differs is in how it works.• In it you can handle the creation and manipulation of data fields as

you see fit.

Page 12: 2CPP13 - Operator Overloading

Copy Constructors• There are three point when a copy constructor will be

called.• When an object is created from another object of the same type.• When an object is passed by value as a parameter to a function.• When an object is returned from a function.

• If a copy constructor is not defined, one will be created by the compiler.• This is fine if you’re not working with dynamic data.

Page 13: 2CPP13 - Operator Overloading

Stack Exampleclass Stack {private: int size; int *elements;

public: void push(int); int pop(); Stack();};

#include "Stack.h"

Stack::Stack() { elements = new int [100]; size = 0;}

int Stack::pop() { int popped;

if (size == 0) { return -1; }

popped = elements[size-1]; size -= 1; return popped;}

void Stack::push(int val) { if (size == 100) { return; }

elements[size] = val; size += 1;}

Page 14: 2CPP13 - Operator Overloading

Stack Example

#include <iostream>#include "Stack.h"

using namespace std;

int main() { Stack my_stack; Stack my_second_stack = my_stack;

my_stack.push (3); my_stack.push (2); my_stack.push (1);

cout << my_stack.pop() << ", " << my_stack.pop() << ", " << my_stack.pop() << endl;

my_second_stack.push (9); my_stack.push (8);

cout << my_second_stack.pop() << endl;

return 1;}

Page 15: 2CPP13 - Operator Overloading

Copy Constructorclass Stack {private: int size; int *elements;

public: void push(int); int pop(); Stack(); Stack (Stack&);};

Stack::Stack (Stack& copy) { elements = new int[100];

for (int i = 0; i < copy.size; i++) { elements[i] = copy.elements[i]; }}

Page 16: 2CPP13 - Operator Overloading

Copy Constructor• This only works when we create an object from an

existing object:• Stack my_second_stack = my_stack

• Not when we create an object afterwards:• Stack my_second_stack;• my_second_stack = my_stack

• For the latter case, we must provided an overloaded assignment operator.

Page 17: 2CPP13 - Operator Overloading

Overloaded =class Stack {private: int size; int *elements;

public: void push(int); int pop(); Stack(); Stack (Stack&); Stack operator= (Stack&);};

Stack Stack::operator =(Stack& copy) { size = copy.size; elements = new int[100];

for (int i = 0; i < size; i++) { elements[i] = copy.elements[i]; } return (*this);}

Page 18: 2CPP13 - Operator Overloading

Notes on Both Approaches• You can access private data members of the parameter

passed in.• this in c++ used to provide a reference to the object in

which the code is defined.• Used to return a reference to the object.

• Code suffers from memory leaks!• Must explicitly delete dynamic memory before assigning new

objects.

Page 19: 2CPP13 - Operator Overloading

Deep Copies• In both cases, the two approaches are used to provide

deep copies of an object.• We don’t just copy a pointer reference, we copy the contents being

pointed to.

• This ensures that our references are clean and not overlapping.• These kind of errors are extremely subtle.

• Need to do this when dynamic data is being stored.

Page 20: 2CPP13 - Operator Overloading

Copy versus Assignment• Copy constructors:

• Create a new object• By copying an old object

• Called when objects are passed or returned by value.• Like all constructors, does not return a value.

• Overloaded =:• Copies an existing object onto another existing object.• Returns a reference to the newly setup object.

• When working with dynamic data, you need to provide both!

Page 21: 2CPP13 - Operator Overloading

Summary• You can overload operators in C++

• But you know… don’t.

• The only time this is needed and appropriate is overloading the equals operator.

• Shallow copies of objects cause side-effects.• And these side-effects are often very difficult to detect.

• Deep copies using copy constructors and overloaded operators are required.