Top Banner
Generic Programming: Templates and Overloading
95

Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity Major theme in development of programming languages Reuse code.

Dec 21, 2015

Download

Documents

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: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Generic Programming:Templates and Overloading

Page 2: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Evolution of Reusability and Genericity

Major theme in development of programming languages• Reuse code to avoid repeatedly reinventing the wheel

Trend contributing to this• Use of generic code• Can be used with different types of data

Function and class templates• Enable programmers to specify an entire range of related

functions and related classes Generic programming

COMP152 2

Page 3: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function Templates (parameterized functions)

Page 4: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Motivation

Initially code was reusable by encapsulating it within functions

Example:• Write

• Then call swap(x,y);

COMP152 4

void swap (int& first, int& second){ int temp = first; first = second; second = temp;}

Page 5: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

To swap variables of different types, write another function• Overloading allows functions to have same name

• Signature (types and numbers of parameters) keep them unique to the compiler

This could lead to a library of swap functions• One function for each standard/primitive type

• Compiler chooses which to use from signature

But … what about swapping user defined types such as an object?• We cannot cover the swap function for ALL possible class objects

COMP152 5

void swap (int& first, int& second){ int temp = first; first = second; second = temp;}

void swap (double& first, double& second){ double temp = first; first = second; second = temp;}

void swap (char& first, char& second){ char temp = first; first = second; second = temp;}

Page 6: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 6

void swap (T& first, T& second){ T temp = first; first = second; second = temp;}

Passing Types (Instead of Fixed Types)

Page 7: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Using function overloading, note how similar each of the swap functions would be• The three places where the type is specified

What if we passed the type somehow? Templates make this possible

• Declare functions that receive both data and types via parameter

Thus code becomes more generic• Easier to reuse and extend to other types

COMP152 7

Page 8: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function Templates

Produce overloaded functions that perform identical operations/algorithms on different types of data

• Programmer writes a single function-template definition• Compiler generates separate object-code functions (function-

template specializations) based on argument types in calls to the function template

COMP152 8

Page 9: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function Templates More compact and convenient form of overloading

• Identical program logic and operations/algorithms for each data type

Function template definition • Written by programmer once• Essentially defines a whole family of overloaded functions• Begins with the template keyword • Contains template parameter list of formal type parameters for the

function template enclosed in angle brackets (<>)• Formal type parameters

Preceded by keyword typename or keyword class Placeholders for fundamental types or user-defined types

COMP152 9

Page 10: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Writing Template A function template is a pattern

• constructed based on given actual types• type parameter said to be "bound" to the actual type passed to it

Calling a function with template type inside the function

COMP152 10

template<typename T> void f() {

T a; …

} f();

Page 11: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

General Form of Template

template<typename TypeParam>

FunctionDefinition

TypeParam is a type-parameter (placeholder) naming the "generic" type of value(s) on which the function operates

FunctionDefinition is the definition of the function, using type TypeParam

COMP152 11

Page 12: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 12

template<typename T>void swap (T& first, T& second){ T temp = first; first = second; second = temp;}

main() {int a,b;double x,y;char m,n;

swap(a,b); // swap<int>(a,b);swap(x,y); // swap<double>(x,y);swap(m,n); // swap<char>(m,n);

}

Page 13: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Template Instantiation In and of itself, the template does nothing When the compiler encounters a template

• it stores the template • but doesn't generate any machine instructions or codes

When a function template is instantiated• Compiler finds type parameters in list of function template• For each type in the function parameter list, type of corresponding argument is

determined• These two function type and argument type are then bound together

E.g., when it encounters a call to swap()• Example: swap(int, int);• it generates an integer instance of swap()

The type will be determined …• by the compiler (at compilation time)• from the type of the arguments passed• when swap() is called

Cannot specify data type at run time

COMP152 13

Page 14: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Example: displayarray.cpp

Function-template specializations are generated automatically by the compiler to handle each type of call to the function template

If an array of user-defined objects is used, need to overload << operator of the object class.

COMP152 14

template <typename T>void display(T array[], int num) { for (int i = 0; i < num; i++) cout << array[i] << " "; cout << endl;}

int main() { double x[] = {1.1, 2.2, 3.3, 4.4, 5.5}; display(x, 5); int num[] = {1, 2, 3, 4}; display(num, 4);}

1.1 2.2 3.3 4.4 5.51 2 3 4

display<double> created

display<int> created

Page 15: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

.h and .cpp Files for Template Functions

Three files: • foo.h (template declaration), • foo.cpp (template definition), and • main.cpp (using template functions)

The compiler, in the compilation of foo.cpp to object codes, has to know the data type input into the template functions, and replace all the template occurrences by the actual data type• Therefore, the callers of the template functions have to be known at compile time. This is different from the non-

template functions where the compiler does not need to know the callers to generate proper object codes.• That means main.cpp has to include both foo.cpp,and hence foo.h• That also means foo.h and foo.cpp have to be combined into one single file

COMP152 15

A function template cannot be split across files for separate compilation

- Specification/declaration and implementation/definition usually are in the same file

- This sometimes causes some inconvenience in makefiles (need to combine .h and .cpp)

Page 16: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Class Templates (parameterized classes)

Page 17: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

class List {public:

List(); // constructorList(const list& list); // copy constructor~List(); // destructor

bool empty() const; // boolean functionint head() const; // access functionsvoid add(int newdata); // add to the headvoid delete(); // delete the head

private:…

};

Motivations:

List of integer, list of doubles, list of characters, list of objects …

Page 18: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

class List {public:

List(); // constructorList(const list& list); // copy constructor~List(); // destructor

bool empty() const; // boolean functionT head() const; // access functionsvoid add(T newdata); // add to the headvoid delete(); // delete the head

private:…

};

Page 19: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

template<typename T>class List {

public:List(); List(const List& list1); ~list();

bool empty() const; T head() const;

void add(T newdata); void delete();

private:T* head;

};

Page 20: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

template<typename T>List::List(){

head=NULL; size=0;}

template<typename T>bool List::empty() const{

}

template<typename T>T List::head() const {

}

Some simple member functions:

Implementation

Page 21: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Other functions …

template<typename T>

List::~List(){

delete T[] head;

}

Page 22: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

How about using ‘typedef’ ? Changes the header file

• Any program that uses this must be recompiled inconvenient and time-consuming

A name declared using typedef can have only one meaning• What if we need two stacks of different types in the same

program?

COMP152 22

Page 23: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

General Form of Class Template

COMP152 23

More than one type parameter may be specified:

template<typename T>class X{

…};

template<typename T1, ..., typename Tn>class X{

…};

X<t1, ...,tn> B;

X<t> A;

Page 24: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Instantiating Class Templates

Instantiate by using declaration of formClassName<Type> object;

Examples:

List<int> intList;

List<string> stringList;

Compiler will generate two distinct definitions of List • two instances: one for int and one for strings

COMP152 24

Page 25: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Rules For Class Templates Definitions of member functions outside class declaration

must be function templates

tempate<typname T> A_class<T>::…

All uses of class name as a type must be parameterized with <…>

A_class<T>…

(compared to function template, the type is ‘deduced’)

Member functions must be defined in the same file as the class declaration

• Same reason as in function template (i.e., compiler needs to know the exact data types at calling to generate appropriate object codes at compile time)

• Sometimes causing inconveniences in makefile (need to combine .h and and .cpp)

COMP152 25

Page 26: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Stack Class Template

Application of all these principles• A Stack class template (Stack.h)• Note that there is not a separate .cpp file

Templates may have more than one type parameter Thus possible to specify a Stack class differently

• Could specify with a dynamic array and pass an integer for the capacity

COMP152 26

Page 27: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

stacktester1.cpp Output Sample Output

COMP152 27

Pushing elements onto doubleStack1.1 2.2 3.3 4.4 5.5Stack is full. Cannot push 6.6Popping elements from doubleStack5.5 4.4 3.3 2.2 1.1Stack is empty. Cannot popPushing elements onto intStack1 2 3 4 5 6 7 8 9 10Stack is full. Cannot push 11Popping elements from intStack10 9 8 7 6 5 4 3 2 1Stack is empty. Cannot pop

Page 28: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

stacktester2.cpp Sample Output

COMP152 28

Pushing elements onto doubleStack1.1 2.2 3.3 4.4 5.5Stack is full. Cannot push 6.6 Popping elements from doubleStack5.5 4.4 3.3 2.2 1.1Stack is empty. Cannot pop Pushing elements onto intStack1 2 3 4 5 6 7 8 9 10Stack is full. Cannot push 11  Popping elements from intStack10 9 8 7 6 5 4 3 2 1Stack is empty. Cannot pop

Page 29: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Default Types Type parameters can have default arguments

• Template header:

template<typename T = string>

• Declaration:

Stack<> myStringStack; // default is string

COMP152 29

Page 30: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Other Parameters Other primitive types (not a generic type) can be parameters of the template

• Can have default arguments• Are treated as consts to generate machine codes• Template header:

template<typename T, int number>

• Declaration:

Stack<double, 100> myDoubleStack;

COMP152 30

Page 31: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Templates and Static Members Each class-template specialization has its own copy of

each static data member• All objects of that specialization share that one static data member• static data members must be defined and, if necessary, initialized

at file scope

Each class-template specialization gets its own copy of the class template’s static member functions

See special_template.cpp for default and static members

COMP152 31

Page 32: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

(Explicit) Specializations Used when a particular type will not work with the general

template or requires customized processing Example for an explicit Stack<Employee> specialization,

where Employee is a defined class

This is a complete replacement for the general template • This does not use anything from the original class template and

can even have different members

COMP152 32

template<>class Stack<Employee>{

// tailor-made implementation here …};

Page 33: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Example

COMP152 33

template<typename T>class X {…};

template<>class X<int> { public: void hello(void);};

// No need to have template<> herevoid X<int>::hello(void){ cout << "hello world" << endl;}

int main(){ X<int> a; a.hello();}

Page 34: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Overloading

Functions overloading Operator overloading

Page 35: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function overloading

Page 36: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function Overloading Overloaded functions have

• Same name• Different sets of parameters

Compiler selects proper function to execute based on number, types and order of arguments in the function call

Commonly used to create several functions of the same name that perform similar tasks, but on different data types and numbers of parameters

COMP152 36

Page 37: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

overload.cpp (1/2)

Defining a square function for ints and doubles

COMP152 37

// function square for int valuesint square(int x){ cout << "square of integer " << x << " is "; return x * x; } // end function square with int argument

// function square for double valuesdouble square(double y) { cout << "square of double " << y << " is "; return y * y; } // end function square with double argument

Page 38: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

overload.cpp (2/2)

Sample Output

Output confirms that the proper function was called in each case

COMP152 38

int main(){ cout << square( 7 ); // calls int version cout << endl; cout << square( 7.5 ); // calls double version cout << endl; return 0; // indicates successful termination} // end main

square of integer 7 is 49square of double 7.5 is 56.25

Page 39: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

More examples ...

#include <stdio.h>

int max(int a, int b) { if (a > b) return a; return b;}

char* max(char* a, char* b) { if (strcmp(a, b) > 0) return a; return b;}

int main() { cout << “max(19, 69) = “ << max(19, 69) << endl; cout << “max(“abc”, “def”) = “ << max(“abc”, “def”) << endl;

}

Page 40: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function Overloading How the compiler differentiates overloaded functions:

• Overloaded functions are distinguished by their signaturesCompiler encodes each function identifier with the number and types of

its parameters to enable type-safe linkage

• Type-safe linkage ensures thatProper overloaded function is called Types of the arguments conform to types of the parameters

Creating overloaded functions with identical parameter lists and different return types is a compilation error• It is ambiguous on which function to call

COMP152 40

Page 41: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Operator overloading: part I (good for users, hard for

developpers

Page 42: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Motivation

42

class Complex {public:

Complex(double re, double im) const;…const Complex add(const Complex& c2) {

…return (Complex(…));

};…

private:double real; double imag;

}Complex add(const Complex& c1, const Complex& c2) {

…return Complex(…,…);

}

main() {Complex a,b,c;c=a.add(b); // member functionc=add(a,b); // non-member (global) function…

}

Page 43: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Operator Overloading: a syntax sugar!

43

‘+’ is a function (operator function),

is called ‘operator+’,

and can be overloaded!

‘a+b’ is ‘operator+(a,b)’ or ‘a.operator+(b)’

a (global) non-member function

a member function

2+3

is

operator+(2,3)

Page 44: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

‘addition operator’ of two complex numbers

44

obj1.add(obj2) obj1 + obj2

The form of a+b is translated into a.operator+(b)

class Complex {public:…

const Complex operator+(const Complex& c2) {…return Complex(…);

};…

}

main() {Complex a,b,c;c=a+b;…

}

Page 45: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

But,

45

‘a+b+c’ is fine: a.add(b.add(c)) ‘a+10.0’ is fine (if we modify it ): a.operator+(10.0) How about ‘10.0+a’ ? 10.0.operator+(a)?

Page 46: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Use a non-member function

46

class Complex {public:

…double real() const;double imag() const;…const Complex operator+(const Complex& c2);const Complex operator+(const double real2);…

}Complex operator+(const double real1, const Complex& c2) {

…return Complex(real(…),imag(…));

}const Complex operator+(const Complex& c1, const Complex& c2) {

…return Complex(real(…),imag(…));

}

main() {Complex a,b,c;c=10.0+a;c=a+10.0;…

}

A call of a+b is then converted to operator+(a,b)

10.0+a operator+(10.0,a) (a normal function call, not a ‘method’ of an object)

If the first operand (or the left operand) is not an object of the same class, we cannot use a ‘member function’, so have to use a normal overloaded function.

Page 47: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

‘Friend’ is coming to help … We can define functions or classes to be friends of a

class to allow them direct access to its private data members

class Complex { ... public: ... friend const Complex operator+(const Complex&, const Complex&); };

const Complex operator+(const Complex& op1, const Complex& op2) { double real = c1.real + c2.real;

double imag = c1.imag + c2.imag; return(Complex(real, imag)); }

47

Access to private data thanks to the ‘friendship’!

Page 48: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Assignment Operator ‘=‘

Assignment operator (=) can be used to assign an object to another object of the same type• Member-wise assignment: each data member of the right object is

assigned to the same data member in the left object

COMP152 48

A a,b;

a = b;

Page 49: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

class T { ... public: ... T& operator=(const T& right);

...};

T& T::operator=(const T& right) {…return *this;

}

main() {

T a,b; …b = a; // b.operator=(a)…

}

49

*this refers to the calling object

Returning a reference allows the chaining of operators

a = b = c = d; a = (b = (c = d))

a.operator=(b.operator=(c.operator=(d)))

it can NOT be a const function, as ‘=‘ modifies the object

Page 50: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

class T { ... public: ... T& operator=(const T& right);

...};

T T::operator=(const T& right) {…return *this;

}

T& T::operator=(const T& right) {if (this == &right) return *this;…return *this;

}

main() {

}

50

1. Return an object: make a temporary object, then return

2. Return a ref: no copy, just the ref. more efficient!

Return an object or a reference?

Page 51: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Returning a reference or a const reference?

COMP152 51

a = b = c always means a = (b = c) as ‘=‘ is right associative, it is a rvalue.

We can write (a=b)=c, depending what a=b returns.

int i=5, j=4;

(i=j)=3; // lvalue, return the new i cout << i<< j ; // get 3 4

(i=3)=4; // lvalue, return the new i cout << i<< j ; // get 4 4

i = j = 3; // get 3 3

Page 52: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

We cannot write (a = b) = c if we return a const ref:

const T& operator=(const T&); We can do (a=b)=c if we return a non-constant ref:

T& operator=(const T&);

COMP152 52

It can be both a l-value and r-value!

Page 53: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

class T { ... public: ... T& operator=(const T& right);

...};

T& T::operator=(const T& right) {if (this == &right) return *this;…return *this;

}

main() {

T a,b; …b = a; // b.operator=(a)…

}

53

1. Const reference for the argument (a r-value)

2. Return a reference to the left-hand side (a l-value), and *this is converted into a reference

3. Check for self-assignment

Summary on ‘=‘ overloading

Page 54: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Function Value Return

COMP152 54

The semantics of function value return are identical to those of initialization (like the semantics of argument passing) A return is to initialize an un-named variable of the returned type. The type of a return expression is checked against the type of the returned type, and all standard and user-defined type conversions are performed.

double f() { return 1;

} // 1 is implicitly converted into double(1)

int* fp() {int local=1;return &local;

} // bad!

int& fr() { int local=1;return local;

} // bad!

Page 55: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 55

X f() { X x; return x;}

‘return x’ returns a temporay object ‘temp’ of class X by constructor (because x is a local object, and to be lost!)

Page 56: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 56

# include <iostream>using namespace std;

class X {public: X() {cout << "constructor\n";} X(const X& x){cout << "copy constructor\n"; }};

// return an object of XX f() { X x; return x;}

// must be rvalueconst X cf() { X x; return x;}

// must be rvalueconst X& crf(X& x){ return x;}

//can be rvalue or lvalueX& rf(X& x){ return x; }

constructor (for X x in main)constructor (for X y in main)

constructor (for X x in f)copy constructor (Unix has that, but not Linux, for return x in f)

constructor (for X x in cf)copy constructor (Unix has that, but not Linux, for return x in cf)

int main() { X x,y;

f() = x; // No compilation error but does nothing

f = cf(); // cfx() = x is error f = rf( y );

f = crf( y ); // crfx( y ) = x is error return 0;}

Page 57: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

A function can return • an object, a constant object, • a reference to an object, and a constant reference to an object

Returning an object or constant object may call the copy constructor to copy the returned value to some temporary object • Compiler dependent – the compiler may do some optimization on function

return so as to minimize calling copy constructor Returning a reference or a constant reference does NOT call the

copy constructor• More efficient• However, remember NOT to return a local variable in your function as a non-

constant reference!

Good practice:• to return a function’s local variable, use return by value or return

by constant value. • to return non-local objects, use return by reference or constant

reference.

COMP152 57

Page 58: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Assign objects of different classesclass T { ... public: ... T& operator=(const T& right);

T& operator=(const X& right); T& operator=(const int right); ...

};

main() {

T a,b;X c,d; …b = a; // b.operator=(a)…a = c;a = 10;

}

58

Page 59: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Input/outputclass T { ...};

ostream& operator<<(ostream& out, const T t) {…return out;

}

istream& operator>>(istream& in, T& t) {…return in;

}

main() {

T a;…cin >> a;cout << a;…

}

59

Before, we wrote a ‘display’ or ‘print’ function.

Page 60: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Which operators to overload?

60

Only those for which it makes sense … … and for which there is a genuine need … … and which the users will expect Typically these are usually appropriate:

= << >>

If the class involves ‘arithmetic type’ (e.g. complex, rational, vector, matrix, …), arithmetic operations should be provided.

Page 61: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Essential operators

class X {X();X(const X&);~X();X& operator=(const X&);

…}

ostream& operator<<(ostream& out, const X x) {…

}

Page 62: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Midterm preparation

No ‘templates’ Programming questions, no multiple choice

questions One A4 paper with notes written or typed on

both sides No calculators or other devices Check last ‘midterm’

Page 63: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Operator overloading: part II

Page 64: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Using Operators on Class Objects Overloading provides concise and intuitve notation

object2 = object1.add(object2); vs. object2 = object1 + object2;

The operators must be overloaded for that class Default operations

• Assignment operator (=)Member-wise assignment between objects

• Address operator (&) returns address of object

• Comma operator (,)evaluates expression to its left then the expression to its right

• Can be overloaded/overruled by the programmer

COMP152 64

Page 65: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Restrictions on Operator Overloading Cannot change

• Precedence of operator (order of evaluation)Use parentheses to force order of operators

• Associativity (left-to-right or right-to-left)2*3*4 (=6*4) vs. 2^3^2 (=2^9)

• Number of operandse.g., !, & or * is unary, i.e., can only act on one operand as in &i or *ptr

• How operators act on built-in/primitive data types (i.e., cannot change integer addition)

Cannot create new operators Remember, static functions only access static data Operators must be overloaded explicitly

• Overloading + and = does not overload +=

COMP152 65

Page 66: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Restrictions on Operator Overloading

Operators that can be overloaded

+ - * / % ^ & |~ ! = < > += -= *=/= %= ^= &= |= << >> >>=

<<= == != <= >= && || ++-- ->* , -> [] () new delete

new[] delete[]

COMP152 66

Operators that cannot be overloaded

. .* ? :

Member functions declaration: bool operator!() const; bool operator==(const T&) const; bool operator<(const T&) const; bool operator!=(const T& right) const; bool operator>( const T& right) const; bool operator<=(const T& right) const; bool operator>=(const T& right) const;

Page 67: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Operators as Class Members

Leftmost object must be of the same class as operator function

Use this keyword to explicitly get left operand argument Operators (), [], -> or some other assignment operator

must be overloaded as a class member function Called when

• Left operand of binary operator is of this class• Single operand of unary operator is of this class

COMP152 67

Page 68: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 68

// subscript operator: can be both modifiable lvalue and rvalue T& operator[](int); // return the object at the index // subscript operator: if you only want it to be an rvalue T operator[](int) const; // constant member function; cannot be lvalue // May also be

// const T& operator[](int) const; // but NOT

// T& operator[](int) const; // (compile error)

T operator()(int, int = 0) const; // at most 2 parameters

The ‘const’ matters, and is part of the prototype,• We call it const overloading (the prototypes above)

The compiler decides based on the type of the calling object. • If it is const object, the const member function will be used.

Sometimes we need this if we want to use a different member function for a const object.

• If it is not a const object, the non-const function will be used, no matter whether it is a rvalue or lvalue

Page 69: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 69

#include <iostream>using namespace std;

class B {public: const int& operator[](int i) const{ cout << "Constant [] function is called" << endl; return data[i]; } int& operator[](int i){ cout << "Non-constant [] function is called" << endl; return data[i]; }private: int data[10];};

int main(){ B b1; const B bc = b1; b1[0]; b1[2] = bc[2]; cout << bc[1] << endl; return 0;}

Non-constant [] function is called (for b1[0])Non-constant [] function is called (for b1[2])Constant [] function is called (for bc[2])Constant [] function is called (for bc[1])0

Page 70: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Operators as Global Functions

Need parameters for both operands Can have object of different class Can be a friend to access private or protected data Both << and >> must be global functions

• Cannot be class members

Overloaded << operator• Left operand is of type ostream&

Such as cout object in cout << classObject

Similarly, overloaded >> has left operand of istream&• Such as cin object in cin >> classObject

COMP152 70

Page 71: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Global Functions: Commutative Operators

May want + to be commutative• So both “a + b” and “b + a” work

Suppose we have two different classes• If the overloaded operator is a member function, then its class is on left

HugeIntClass + long int• Can be member function for HugeIntClass

HugeIntClass + HugeIntClass• Can be member function as well

long int + HugeIntClass• For this to work, + needs to be a global overloaded function

COMP152 71

HugeInt& operator+( long, HugeInt ); // function overloading HugeInt& operator+( HugeInt, long ); HugeInt& operator+( HugeInt, HugeInt );

Page 72: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Overloading Unary Operators Can overload as member function with no arguments Can overload as global function with one argument

• Argument must be class object or reference to class object

If member function, needs no arguments• bool operator!() const;

If global function, needs one argument• bool operator!( const T& ), i.e., !f becomes operator!(f)

COMP152 72

Page 73: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Overloading Binary Operators Member function: one argument

• const T& operator+=(const T&);• s1 += s2; // a string• s1 += s2 += s3; // same as s1 += ( s2 += s3 );• (s1 += s2) += s3; // compiler yells

Global function: two arguments• One of the arguments must be class object or reference• const T& operator+=(T&, const T&);

// no const for the first argument• y += z becomes operator+=( y, z )

Note that int type provides a variant of lvalue:

COMP152 73

int i=2,j=4;(j +=i) += 2; // return the new jcout << i << j; // output 2 8

Page 74: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Case Study: String Class Build class String

• String creation, manipulation• Similar to class string in standard library

Conversion constructor• Any single-argument constructor• Turns objects of other types into class objects• Example: String s1( "happy" );

Creates a String from a char *

Overloading function call operator String.h, String.cpp, stringtester.cpp

COMP152 74

Page 75: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

stringtester.cpp Sample Output (1/3)

COMP152 75

Conversion (and default) constructor: happyConversion (and default) constructor: birthdayConversion (and default) constructor:s1 is "happy"; s2 is " birthday"; s3 is ""

The results of comparing s2 and s1:s2 == s1 yields falses2 != s1 yields trues2 > s1 yields falses2 < s1 yields trues2 >= s1 yields falses2 <= s1 yields true

Testing !s3:s3 is empty; assigning s1 to s3;operator= calleds3 is "happy"

s1 += s1 += s2 yields s1 = happy birthdayhappy birthday

Page 76: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

stringtester.cpp Sample Output (2/3)

COMP152 76

s1 += " to you" yieldsConversion (and default) constructor: to youDestructor: to yous1 = happy birthdayhappy birthday to you

Conversion (and default) constructor: happy birthdayCopy constructor: happy birthdayDestructor: happy birthdayThe substring of s1 starting atlocation 0 for 14 characters, s1(0, 14), is:happy birthday

Destructor: happy birthdayConversion (and default) constructor: appy birthday to youCopy constructor: appy birthday to youDestructor: appy birthday to youThe substring of s1 starting atlocation 15, s1(15), is: appy birthday to you

The constructor and destructor are called

for the temporary String

Page 77: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

stringtester.cpp Sample Output (3/3)

COMP152 77

Destructor: appy birthday to youCopy constructor: happy birthdayhappy birthday to you

*s4Ptr = happy birthdayhappy birthday to you

Assigning *s4Ptr to *s4Ptroperator= calledAttempted assignment of a String to itself*s4Ptr = happy birthdayhappy birthday to youDestructor: happy birthdayhappy birthday to you

s1 after s1[0] = 'H' and s1[6] = 'B' is: Happy Birthdayhappy birthday to you

Attempt to assign 'd' to s1[30] yields:Destructor: happyDestructor: birthdayDestructor: Happy Birthdayhappy birthday td you

Page 78: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Overloading ++ and -- Increment/decrement operators can be overloaded Prefix increment: ++x Postfix increment: x++ Suppose we want to add 1 to a Date object d1 Member-function prototype for prefix increment

• Date& operator++(); // return a reference for

// successive operation: y=++++x• ++d1 becomes d1.operator++()

Global-function prototype for prefix increment• Date& operator++( Date& );• ++d1 becomes operator++( d1 )

COMP152 78

Page 79: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Postfix Increments Postfix increment has a dummy integer parameter• d++• An int with value 0

Overload operator++ with different function parameters Member-function prototype for postfix increment:• T operator++( int ); // must be rvalue;• d1++ becomes d1.operator++(0)

The value returned is a temporary variable inside the function, i.e., it does not and cannot return a reference • Can NOT use d++++ to increment d twice (because it is the

temporary variable returned, not the incremented object)• y = d++++ will have y equal to d+2.

Global-function prototype for postfix increment• T operator++( T&, int ); • d1++ becomes operator++( d1, 0 )

COMP152 79

Page 80: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Overloading ++ and --

Return values• Prefix increment (++x)

Increment and then return the incremented objectReturn by reference (Date &) so that we can use ++++x to increment x twiceTheoretically can be a lvalue (i.e., can be assigned like ++x = 4), though we

almost never use it as lvalueNote that y = ++x assigns y the value of ++x, NOT making y an alias of x!

• Postfix increment (x++)Store x in a temporary object, increment x, and then return the temporary

objectReturns by value (Returns temporary object with the object’s old value)Must be rvalue (cannot be on left side of assignment), e.g., y = x++; // not x++=4;

All this applies to decrement operators as well

COMP152 80

Date& operator++(); // prefix increment operator, ++DateDate operator++( int ); // postfix increment operator, Date++

Page 81: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Case Study: A Date Class Overloaded increment operator

• Change day, month and year

Function to test for leap years Function to determine if a day is last of month Date.h, Date.cpp, datetester.cpp

COMP152 81

Page 82: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Date.h

COMP152 82

class Date{ friend ostream& operator<<( ostream&, const Date& );public: // default constructor Date( int m = 1, int d = 1, int y = 1900 ); void setDate( int, int, int ); // set month, day, year Date& operator++(); // prefix increment operator, ++Date Date operator++( int ); // postfix increment operator, Date++ const Date& operator+=( int ); // add days, modify object bool leapYear( int ) const; // is date in a leap year? bool endOfMonth( int ) const; // is date at the end of month?private: int month; int day; int year; static const int days[]; // static member variable; array of days per month void helpIncrement(); // utility function incrementing date}; // end class Date

Note the difference between prefix and postfix increment

Page 83: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Date.cpp (1/5)

COMP152 83

#include "Date.h"

// initialize static member at file scope; one classwide copyconst int Date::days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// Date constructorDate::Date( int m, int d, int y ) { setDate( m, d, y ); } // end Date constructor

// set month, day and yearvoid Date::setDate( int mm, int dd, int yy ) { month = ( mm >= 1 && mm <= 12 ) ? mm : 1; year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900;

// test for a leap year if ( month == 2 && leapYear( year ) ) day = ( dd >= 1 && dd <= 29 ) ? dd : 1; else day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1;} // end function setDate

Page 84: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Date.cpp (2/5)

COMP152 84

// overloaded prefix increment operator Date &Date::operator++(){ helpIncrement(); // increment date return *this; // reference return to create an lvalue} // end function operator++

// overloaded postfix increment operator; note that the // dummy integer parameter does not have a parameter nameDate Date::operator++( int ){ Date temp = *this; // hold current state of object helpIncrement();

// return unincremented, saved, temporary object return temp; // value return; not a reference return} // end function operator++

Postfix increment updates object and returns a copy of the original

Do not return a reference to temp, because returning a reference may make the variable a lvalue. Since temp is a local variable, it will be destroyed leading to access error

Page 85: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Date.cpp (3/5)

COMP152 85

// add specified number of days to dateconst Date& Date::operator+=( int additionalDays ) { for ( int i = 0; i < additionalDays; i++ ) helpIncrement(); return *this; // enables cascading} // end function operator+=

// if the year is a leap year, return true; otherwise, return falsebool Date::leapYear( int testYear ) const { if ( testYear % 400 == 0 || (testYear % 100 != 0 && testYear % 4 == 0) ) return true; // a leap year else return false; // not a leap year} // end function leapYear

// determine whether the day is the last day of the monthbool Date::endOfMonth( int testDay ) const { if ( month == 2 && leapYear( year ) ) return testDay == 29; // last day of Feb. in leap year else return testDay == days[ month ];} // end function endOfMonth

Page 86: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Date.cpp (4/5)

COMP152 86

// function to help increment the datevoid Date::helpIncrement(){ // day is not end of month if ( !endOfMonth( day ) ) day++; // increment day else if ( month < 12 ) // day is end of month and month < 12 { month++; // increment month day = 1; // first day of new month } // end if else // last day of year { year++; // increment year month = 1; // first month of new year day = 1; // first day of new month } // end else} // end function helpIncrement

Page 87: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Date.cpp (5/5)

COMP152 87

// overloaded output operatorostream& operator<<( ostream& output, const Date& d ){ static char* monthName[ 13 ] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; output << monthName[ d.month ] << ' ' << d.day << ", " << d.year; return output; // enables cascading} // end function operator<<

Page 88: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

datetester.cpp

COMP152 88

Date d1; // defaults to January 1, 1900Date d2( 12, 27, 1992 ); // December 27, 1992Date d3( 0, 99, 8045 ); // invalid date

cout << "d1 is " << d1 << "\nd2 is " << d2 << "\nd3 is " << d3;cout << "\n\nd2 += 7 is " << ( d2 += 7 );

d3.setDate( 2, 28, 1992 );cout << "\n\n d3 is " << d3;cout << "\n++d3 is " << ++d3 << " (leap year allows 29th)";

Date d4( 7, 13, 2002 );cout << "\n\nTesting the prefix increment operator:\n“ << " d4 is " << d4 << endl;cout << "++d4 is " << ++d4 << endl;cout << " d4 is " << d4;cout << "\n\nTesting the postfix increment operator:\n“ << " d4 is " << d4 << endl;cout << "d4++ is " << d4++ << endl;cout << " d4 is " << d4 << endl;

Demonstrate prefix increment

Demonstrate postfix increment

Page 89: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

datetester.cpp Sample Output

COMP152 89

d1 is January 1, 1900d2 is December 27, 1992d3 is January 1, 1900 d2 += 7 is January 3, 1993 d3 is February 28, 1992++d3 is February 29, 1992 (leap year allows 29th) Testing the prefix increment operator: d4 is July 13, 2002++d4 is July 14, 2002 d4 is July 14, 2002 Testing the postfix increment operator: d4 is July 14, 2002d4++ is July 14, 2002 d4 is July 15, 2002

Page 90: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Casting: explicit type conversion

Casting:static_cast<T> x;

i = static_cast<int> d;

Function-style cast: T(x); it calls the constructor, but equivalent to static_cast for built-in

types

i = int(d);

Old C style: (T) x;

i = (int) d;

COMP152 90

Page 91: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Convert a primitive type to a class

Use constructors t = T(i);

how to do if T is a primitive type for an object of class X? int(x)?

Overload the assignment t = i;

T operator=(int i);

COMP152 91

Page 92: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Conversion operator: from X to T

class X {

operator T() const;

}

X::operator T() const { … };

X x;

T t;

t = x // t = T(x);

// t = x.T();

Page 93: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

Example PrototypeA::operator char*() const;• Casts class A to a temporary char *• static_cast<char*>(s) calls s.char*()

Same as (char*) s• static_cast<float>(obj) calls obj.float()

Same as (float)obj

Casting can sometimes prevent the need for overloading• Suppose class String can be cast to char*• cout << s; // s is a String: Compiler implicitly converts s to

char* for output• Do not have to overload <<

COMP152 93

Page 94: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

COMP152 94

# include <iostream># include <string>using namespace std;

class record{ // 1 to 1 mapping between key and recordpublic: record(string str = ""){ name = str; key = str.size(); }

operator int() const { // no return type; for implicit casting to compare records return key; }

private: int key; // search key of the string string name; // … and some other fields if necessary};

int main(){ record r1; record r2("COMP"); record r3("152"); int k;

cout << r1 << endl; // implicit cast r1 to int k = r2; // implicit casting cout << k << endl; if( r3 < k ) // casting r3 to int cout << "r3 < k\n";

return 1;}

04r3 < k

Page 95: Generic Programming: Templates and Overloading. Evolution of Reusability and Genericity  Major theme in development of programming languages Reuse code.

How to ‘hide’ an operator?class X {private:

void operator=(const X&);void operator&();void operator,(const X&);…

}

Void f(X a, X b) {a=b; // error: operator= private&a; // error: operator& privatea,b; // error: operator, private

}