Software design and c programming
This presentation is the property of its rightful owner.
Sponsored Links
1 / 56

Software Design and C++ Programming PowerPoint PPT Presentation


  • 39 Views
  • Uploaded on
  • Presentation posted in: General

Software Design and C++ Programming. Lecture 4 Operator Overloading and Streamed I/O. Contents. Introduction Operators in C++ Operator overload functions Member function v friend function overloading Converting between types Overloading the assignment operator

Download Presentation

Software Design and C++ Programming

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Software design and c programming

Software Design and C++ Programming

Lecture 4

Operator Overloading and Streamed I/O


Contents

Contents

  • Introduction

  • Operators in C++

  • Operator overload functions

  • Member function v friend function overloading

  • Converting between types

  • Overloading the assignment operator

  • Overloading the array subscripting operator

  • Example – A Date class

  • Introduction to streams

  • The ostream and istream classes

  • User defined input/ouput

  • Other features of streams


Introduction

Introduction

  • Operator overloading is a powerful feature of C++

  • It provides programmers with a concise notation for manipulating user defined objects

  • It is simple to implement given a few basic rules

  • It is also used in providing input/output capabilities via the Stream classes as we shall see in the next lecture


Operators in c

Operators in C++

  • C++ has a rich collection of operators most of which are common to other programming languages

  • It is the standard arithmetic and logical operators

    • + - * / % & ! >> << || && == etc

  • It has thearray indexing and function evaluation operators

    • [] ()

  • It has the assignment operators

    • = += -= *= /= &= |= etc


Software design and c programming

  • It has the auto increment and decrement operators

    • ++ --

  • It has the pointer de-referencing and address of operators

    • * &

  • It has the memory management operators

    • new delete new[] delete[]


Software design and c programming

  • We can divide up the set of operators into unary and binary operators

  • A unary operator has one operand

  • Examples

if (!x){..}// unary operator !, operand x

x++;// post-fix operator ++, operand x

--x;// pre-fix operator --, operand x

int y=a[5];// operator [], operand a


Software design and c programming

  • A binary operator has two operands

  • Examples

int z=x+y;// binary operator +, operands x and y

bool z=x&&y;// binary operator && operands x and y

x+=y;// binary operator +=, operands x and y


Operator overload functions

Operator overload functions

  • In order to overload and operator op, a function operator op must be defined

    • operator+ to overload +

    • operator+= to overload +=

    • operator[] to overload []

    • etc

  • We can either provide member functions of a class or external functions (possibly friend functions of a class)


Software design and c programming

  • Restrictions on operator overloading

    • The precedence of an operator cannot be changed

    • The arity of an operator cannot be changed

      • We cannot redefine a binary operator to be unary or vice verse

    • The associativity of an operator cannot change

      • Whether it applies left to right or right to left


Example

Example

  • We can define a complex class to represent a complex number

class complex

{

private :

double re, im;

public :

complex(double r,double i) { re = r; im = i;}

friend complex operator +(complex, complex);

friend complex operator -(complex);

};


Software design and c programming

  • We have included 2 friend functions for overloading the binary + operator and unary - operator

complex operator +(complex a,complex b)

{

return complex(a.re + b.re , a.im + b.im);

}

complex operator -(complex a)

{

return complex(-a.re, -a.im);

}


Software design and c programming

  • We can also implement the overload functions as member functions

    • In this case, this replaces one of the arguments

class complex

{

private :

double re, im;

public :

complex(double r,double i) { re = r; im = i;}

complex operator +(complex);

complex operator -();

};


Software design and c programming

complex complex::operator +(complex a)

{

return complex(re + a.re , im + a.im);

}

complex complex::operator -()

{

return complex(-re, -im);

}


Software design and c programming

  • The class can now be used as follows

void main()

{

complex z1(3.0,2.0),z2(3.0,-5.0),z3,z4;

z3 = z1 + z2;// overload operator+

z4=-z3;// overload operator-

}


Software design and c programming

  • z1 + z2 is implemented as operator+(z1,z2) when a global function overload is used and z1.operator+(z2) when a member function overload is used

  • -z3 is implemented as operator-(z3) when a global function overload is used and z3.operator-() when a member function overload is used


Converting between types

Converting between types

  • It is often necessary to convert data of one type into data of another type

    • This is done implicitly by the compiler when we, for example, add an integer variable to a floating point variable

    • However, for user defined types, the compiler cannot know in advance how to do these conversions

  • Two mechanisms exist in C++ to convert data types

    • Conversion constructor

    • Conversion operator


Conversion constructor

Conversion constructor

  • Suppose we wanted to write the following simple piece of code

void main()

{

complex z1,z2;

z1 = z2 + 3.0;

}


Software design and c programming

  • We could write an operator overload function operator+(complex,double)

    • But we would need to repeat this for every other operator (eg. -,*,/)

  • The solution is to write a complex->double conversion constructor

complex :: complex(double d)

{

re = d;

im = 0;

}


Software design and c programming

  • z2+3.0 is now interpreted as :

    operator+(z2,complex(3.0))

  • This will cause problems if we have implemented operator+() as a member function

  • z2+3.0 must be interpreted in the same way as 3.0+z2 (addition is commutative)

  • Member function implementation of z2+3.0 is z2.operator(complex(3.0))

  • There is no equivalent implementation of 3.0+z2


Conversion operator

Conversion operator

  • This is used to to convert an object of one class into an object of another class or into a built in type (int, float, char etc)

  • Sometimes called a cast operator as it essentially overloads the cast () operation

  • Declared as a member function of some class, operator X() specifies how to convert an object of this class into an object of type X


Software design and c programming

  • As a (silly) example, we could define a member function double() to convert a complex to a double by taking the real part

class complex

{

private :

double re, im;

public :

complex(double r,double i) { re = r; im = i;}

operator double() {return re;}

};


Software design and c programming

  • If we then cast a complex to a double, the conversion operator is called

void main()

{

complex z1(1,0,2.0);

double x=(double) z1;// calls double(), x=1.0

}


Overloading the assignment operator

Overloading the assignment operator

  • A powerful feature of operator overloading is overloading the assignment operator =

  • This allows us to specify the action of the statement a=b for two objects a and b of some class

  • For our simple complex class, implementing operator= is not necessary

    • z1=z2 causes a default member-wise assignment to be implemented

    • z1.re=z2.re, z1.im=z2.im


Software design and c programming

  • We can see how assignment overload becomes important by considering a simple String class

    • Memory for the string is allocated dynamically in the constructor


Software design and c programming

class String

{

private:

char *p;// pointer to string data

int size;// length of string

public:

String (int sz) { p = new char[size = sz];}

~String( );

int getSize( ) { return size; }

char* getp( ) { return p;}

};


Software design and c programming

  • Without an overloaded assignment operator, assignment involves member-wise copy which doesn’t transfer the data

    • It just copies the pointers

main( )

{

string s1(3);// string of 3 chars

string s2(3);// string of 3 chars

s1 = s2;// are you sure?

}


Software design and c programming

“a”, “b”, “c”,

“a”, “b”, “c”,

Before assignment

s1.p

s2.p

“d”, “e”, “f”,

After assignment

s1.p

“d”, “e”, “f”,

s2.p


Software design and c programming

  • An assignment overload operatordefined asString& String::operator = (String& a) uses strcpy() to ensure data is copied

String& String::operator = (String& a)

{

if (this != &a)// avoid s = s assignment

{

delete p;

p = new char[size = a.getSize( )];

strcpy(p,a.getp( ));// copy *a.p into *p

}

return *this;

}


Software design and c programming

“a”, “b”, “c”,

“d”, “e”, “f”,

Before assignment

s1.p

s2.p

“d”, “e”, “f”,

After assignment

s1.p

s2.p

“d”, “e”, “f”,


Software design and c programming

  • Why does operator=(String) return a String reference?

  • Assignment as a right to left associativity

  • A statement like x=y=z is implemented as (x=(y=z))

    • The result of y=z is a reference to object y

    • This then appears in the x=y assignment

  • This ‘trick’ is also extensively used in streamed i/o


Overloading the array subscripting operator

Overloading the array subscripting operator

  • The [] operator normally used for array access can be overloaded

    • It enables us to design a safe array class where attempts to access beyond the bounds of the array are flagged


Software design and c programming

class SafeArray

{

private:

int* data;

int numPoints;

public:

SafeArray(int);

int& operator[](int);

};


Software design and c programming

int& SafeArray::operator[](int index)

{

if ((index<0)||(index>=numPoints))

{

printf( “Index array out of range ”);

exit(1);// exit program

}

return data[index];

}


Software design and c programming

  • Why does operator[] return a reference?

    • Allows array values to be set as well as accessed using the overload function

    • In other words, the returned value can be used as an lvalue

void main()

{

SafeArray sa(10);// 10 point safe array

int j=sa[3];// Access value

sa[5]=5;// Set value

int k=sa[10];// Out of range!

}


Example a date class

Example. A Date class

  • We can design a Date class which uses overloaded ++ operator functions to add 1 to the day

    • Program statements such as date++ and ++date will then increment the date

    • We have to think carefully about the differences between the post and pre-increment overload functions


Software design and c programming

class Date

{

private:

int day,month,year;

void helpIncrement();

static const int days[];

public:

Date(int d, int m, int y)

{day=d;month=m;year=y;}

Date& operator++();// pre-increment

Date operator++(int);// post-increment

int endOfMonth(int) const;

int leapYear(int) const;

};


Software design and c programming

  • days[] is a convenience array for storing the days per month

  • helpIncrement() is a convenience function for helping to increment the day

  • endOfMonth() uses the days[] array to determine if a given day is the last in the month (taking into account leap years)

const int Date::days[]=

{0,31,28,31,30,31,30,31,31,30,31,30,31};


Software design and c programming

void Date::helpIncrement()

{

if (!endOfMonth(day))

++day;

else

if (month<12)

{

++month;

day=1;

}

else

{

++year;

month=day=1;

}

}


Software design and c programming

Date& Date::operator++()

{

// Pre-increment operator

helpIncrement();

return *this;// reference returned

}

Date Date::operator++(int)

{

//Post increment operator

Date temp=*this;// current object state

helpIncrement();

return temp;// can’t return reference

}


Software design and c programming

  • The pre-increment operator overload function returns a reference so that pre-incremented Date objects can be used as lvalues (Date ++d=….)

  • We can’t do this for the post increment overload function as we can’t return a reference to a temporary local variable

    • In any case syntax such as Date d++=… is not allowed


Software design and c programming

Introduction to streams

  • C++ provides an extensive set of input/output capabilities

  • Stream based input/output relies extensively on operator overloading as well as being object oriented

    • Specific I/O routines are called depending on the data type of the object being input or output

  • Users can specify how to perform I/O for objects or programmer defined types


Software design and c programming

The ostream and istream classes

  • The iostream library provides the ostream class for stream-based output and the istream class for stream-based input

  • These classes provide overload functions for the << and >> operators

    • << - stream insertion operator for output

    • >> - stream extraction operator for input

  • Overload functions for the primitive types are provided

  • Overload functions can easily be provided for programmer defined classes


Software design and c programming

The ostream class

class ostream

{

.

.

public :

ostream& operator << (const char*);

ostream& operator<<(char);

ostream& operator<<(int);

ostream& operator<<(double);

ostream& operator<<(const void*);

.

.

}


Software design and c programming

  • All C++ programs have access to an ostream object cout

  • ostream overload functions automatically called by matching the data types

  • The << operator has left-to-right associativity so multiple objects can be output in one statment


Software design and c programming

Example

int x=10;

cout << "x = " << x;// Outputs “x= 10”

  • Implemented as (cout.operator<<(“x=“)).operator<<(x);

  • Overload functions ostream.operator<<(char*) and ostream.operator<<(int) called


Software design and c programming

The istream class

class istream

{

.

.

public :

istream& operator >> (char*);

istream& operator>>(char&);

istream& operator>>(int&);

istream& operator>>(double&);

.

.

}


Software design and c programming

  • All C++ programs have access to an istream object cin

  • istream overload functions take reference arguments as they modify the arguments

  • The >> operator has left-to-right associativity so multiple objects can be input in one statement

  • operator>>() functions skips white space characters (blanks, tabs, newline, formfeed, carriage return) on the input stream in the same way as scanf() )


Software design and c programming

Example

void main()

{

int i1, i2;

float f;

cout << "Input 2 ints and a float \n";

cin >> i1 >> i2 >> f;

}


Software design and c programming

  • Using right to left associativity, the input is implemented as(((cin >> i1) >> i2) >> f);

  • operator>>(int&) is called twice and operator>>(float&) is called once

  • The values input must be separated by whitespace characters (blanks, tabs, cr) and not commas!


Software design and c programming

User defined input/ouput

  • We can add overloaded operator>>() and operator<<() functions to our own classes

  • They must be overloaded as friend functions of the class and not member functions

    • Obviously they are implemented as binary operators with the first operand cin or cout

  • We must remember to return a reference to an ostream or istream object


Software design and c programming

Example

  • We can add input and output facilities to our Date class

  • Enables a user friendly way of displaying and inputting the current date


Software design and c programming

class Date

{

private:

int day,month,year;

void helpIncrement();

static const int days[];

public:

Date(int d, int m, int y){day=d;month=m;year=y;}friend ostream& operator<<(ostream&, const Date&);

friend istream& operator>>(istream&, Date&);

Date& operator++();// pre-increment

Date operator++(int);// post-increment

int endOfMonth(int) const;

int leapYear(int) const;

};


Software design and c programming

ostream& operator<<(ostream& os, const Date& d)

{

static char*

monthName[13]={“”,”Jan”,”Feb”,”March”,

”April”,”May”,”June”,”July”,”Aug”,”Sept”,

”Oct”,”Nov”,”Dec”};

os<<monthName[d.month] << “ “ << d.day

<< “ “ << d.year;

return os;

};

istream& operator>>(istream& is, Date& d)

{

cout<<“Input the date (dd/mm/yy) “;

is >> d.day >> d.month >> d.year;

return is;

};


Software design and c programming

void main()

{

Date d;

cout << “Input the date : “;

cin >> d;

cout << “The date is “ << d;

}


And finally

And finally…..

  • We have covered some basic ideas about operator overloading and streamed I/O

  • Operator overloading provides user defined classes with elegant notation for expressing manipulations of objects

  • There are more advanced applications of operator overloading such as

    • Overloading new and delete for advanced memory management routines

    • Overloading -> and * for ‘smart’ pointer access


Software design and c programming

  • There are also more advanced features of streams including :

    • File access. Streams can be attached to filenames allowing the whole set of stream functionality to be applied to file I/O

    • Formatting. Field width, field precision (for floating point output), formatting of integer output (decimal, hex, octal).

    • String streams. Streams can be attached to arrays of characters which allows easy conversion of strings into constituent parts (similar to sprintf() and sscanf())


  • Login