c++ programming university of wollongong 2011 - classes

20
Applied Programming CSCI124 Classes Week 7 Applied Programming In our revision example, we approached the In our revision example, we approached the problem of setting up a database by specifying problem of setting up a database by specifying the data for the problem and the operations upon the data for the problem and the operations upon that data. that data. We ultimately had to decide the way it was stored We ultimately had to decide the way it was stored and how we implemented the operations. and how we implemented the operations. But we started by describing the data and what But we started by describing the data and what we would do with it. we would do with it. Applied Programming This logical view of data: This logical view of data: what is represented what is represented what operations can be performed what operations can be performed form an form an abstract data type abstract data type The differences between such user defined types The differences between such user defined types and the built and the built- ins are minimal. ins are minimal. C++ uses the C++ uses the class class to attain this to attain this abstraction abstraction. Applied Programming Consider the following linked list. Consider the following linked list. struct struct Cust Cust; // forward reference ; // forward reference typedef typedef Cust Cust* * CustPtr CustPtr; struct struct Cust Cust { char name[30]; char name[30]; int int partysize partysize; CustPtr CustPtr next; next; }; }; Applied Programming We represent the linked list of customers by a We represent the linked list of customers by a pointer to the head of the list, namely pointer to the head of the list, namely CustPtr CustPtr Head; Head; We have 3 functions to reference this structure. We have 3 functions to reference this structure. void void Initialise(CustPtr Initialise(CustPtr& Head); & Head); void void Add(char Add(char name[], name[], int int psize psize, , CustPtr CustPtr& Head); & Head); bool bool Remove(char Remove(char name[], name[], int int& & psize psize, , CustPtr CustPtr& Head); & Head); If we only had one list we could hide the If we only had one list we could hide the Head Head within the file scope of the functions. within the file scope of the functions. Applied Programming class class LinkedList LinkedList { public: public: void Initialise(); void Initialise(); void void Add(char[],int Add(char[],int); ); bool bool Remove(char[],int Remove(char[],int&); &); private: private: CustPtr CustPtr Head; Head; }; }; The The filescope filescope Head Head has become a has become a private private member of the class. member of the class. The global functions are The global functions are public public members. members. This is the interface component. This is the interface component.

Upload: eword

Post on 17-Jul-2016

6 views

Category:

Documents


0 download

DESCRIPTION

C++ Programming University of Wollongong 2011 - Classes

TRANSCRIPT

Page 1: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

CSCI124

Classes

Week 7

Applied Programming

In our revision example, we approached the In our revision example, we approached the problem of setting up a database by specifying problem of setting up a database by specifying the data for the problem and the operations upon the data for the problem and the operations upon that data.that data.

We ultimately had to decide the way it was stored We ultimately had to decide the way it was stored and how we implemented the operations.and how we implemented the operations.

But we started by describing the data and what But we started by describing the data and what we would do with it.we would do with it.

Applied Programming

This logical view of data:This logical view of data:•• what is representedwhat is represented•• what operations can be performedwhat operations can be performedform anform an

abstract data typeabstract data type

The differences between such user defined types The differences between such user defined types and the builtand the built--ins are minimal.ins are minimal.

C++ uses the C++ uses the classclass to attain this to attain this abstractionabstraction..

Applied Programming

Consider the following linked list.Consider the following linked list.

structstruct CustCust; // forward reference; // forward referencetypedeftypedef CustCust* * CustPtrCustPtr;;

structstruct CustCust{{

char name[30];char name[30];intint partysizepartysize;;CustPtrCustPtr next;next;

};};

Applied Programming

We represent the linked list of customers by a We represent the linked list of customers by a pointer to the head of the list, namelypointer to the head of the list, namely

CustPtrCustPtr Head;Head;

We have 3 functions to reference this structure.We have 3 functions to reference this structure.

void void Initialise(CustPtrInitialise(CustPtr& Head);& Head);void void Add(charAdd(char name[], name[], intint psizepsize, , CustPtrCustPtr& Head);& Head);boolbool Remove(charRemove(char name[], name[], intint& & psizepsize, , CustPtrCustPtr& Head);& Head);

If we only had one list we could hide the If we only had one list we could hide the HeadHead

within the file scope of the functions.within the file scope of the functions.Applied Programming

class class LinkedListLinkedList{{

public:public:void Initialise();void Initialise();void void Add(char[],intAdd(char[],int););boolbool Remove(char[],intRemove(char[],int&);&);

private:private:CustPtrCustPtr Head;Head;

};};

The The filescopefilescope HeadHead has become a has become a privateprivate

member of the class.member of the class.The global functions are The global functions are publicpublic members.members.

This is the interface component.This is the interface component.

Page 2: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

The The filescopefilescope HeadHead has become a has become a privateprivate

member of the class.member of the class.The global functions are The global functions are publicpublic members.members.

This is the interface component.This is the interface component.

It appears in the header file It appears in the header file List.hList.h along with along with the declaration of the the declaration of the structstruct..

How do we implement such functions?How do we implement such functions?

We have a special syntax.We have a special syntax. Applied Programming

void void LinkedList::InitialiseLinkedList::Initialise()(){{

Head = 0;Head = 0;}}

This is the same as before with the replacement This is the same as before with the replacement of the argument by the of the argument by the LinkedListLinkedList:::: prefix to prefix to the function name.the function name.

Note also that the variable Note also that the variable HeadHead is accessed in is accessed in the usual manner.the usual manner.

The other functions are as follows.The other functions are as follows.

Applied Programming

void void Add(charAdd(char name[],intname[],int psize,CustPtrpsize,CustPtr& Head)& Head)

{{

CustPtrCustPtr tmptmp, , currcurr;;

tmptmp = new = new CustCust;;

strcpy(tmpstrcpy(tmp-->>name,namename,name););

tmptmp-->>partysizepartysize = = psizepsize;;

tmptmp-->next = 0;>next = 0;

if (Head != 0)if (Head != 0){{

currcurr = Head;= Head;while (while (currcurr-->next) // is this the end?>next) // is this the end?

currcurr = = currcurr-->next;>next;currcurr-->next = >next = tmptmp;;

}}elseelse

Head = Head = tmptmp;;}} Applied Programming

void void LinkedList::Add(charLinkedList::Add(char name[], name[], intint psizepsize))

{{

CustPtrCustPtr tmptmp, , currcurr;;

tmptmp = new = new CustCust;;

strcpy(tmpstrcpy(tmp-->>name,namename,name););

tmptmp-->>partysizepartysize = = psizepsize;;

tmptmp-->next = 0;>next = 0;

if (Head != 0)if (Head != 0){{

currcurr = Head;= Head;while (while (currcurr-->next) // is this the end?>next) // is this the end?

currcurr = = currcurr-->next;>next;currcurr-->next = >next = tmptmp;;

}}elseelse

Head = Head = tmptmp;;}}

Applied Programming

void void LinkedList::Add(charLinkedList::Add(char name[], name[], intint psizepsize))

{{

CustPtrCustPtr tmptmp, , currcurr;;

tmptmp = new = new CustCust;;

strcpy(tmpstrcpy(tmp-->>name,namename,name););

tmptmp-->>partysizepartysize = = psizepsize;;

tmptmp-->next = 0;>next = 0;

if (if (HeadHead != 0)!= 0){{

currcurr = = HeadHead;;while (while (currcurr-->next) // is this the end?>next) // is this the end?

currcurr = = currcurr-->next;>next;currcurr-->next = >next = tmptmp;;

}}elseelse

HeadHead = = tmptmp;;}} Applied Programming

boolbool LinkedList::Remove(charLinkedList::Remove(char name[], name[], intint& & psizepsize)){{

CustPtrCustPtr tmptmp;;

if (Head == 0)if (Head == 0)return false;return false;

strcpy(name,Headstrcpy(name,Head-->name);>name);psizepsize = Head= Head-->>partysizepartysize;;

// // make a copy of the pointer to current headmake a copy of the pointer to current headtmptmp = Head;= Head;Head = Head = HeadHead-->next; // change the head>next; // change the headdelete delete tmptmp; // delete old head's memory; // delete old head's memoryreturn true;return true;

}}

Page 3: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

So, where does the class get access to So, where does the class get access to HeadHead??It's in the It's in the privateprivate section of the class.section of the class.

In summary, the class has the following syntax In summary, the class has the following syntax (for now)(for now)

class class classnameclassname{{

public:public:assorted userassorted user--accessible accessible functions,etcfunctions,etc..

private:private:data (& functions) hidden from the userdata (& functions) hidden from the user

};};Applied Programming

class class classnameclassname{{

public:public:assorted userassorted user--accessible accessible functions,etcfunctions,etc..

private:private:data (& functions) hidden from the userdata (& functions) hidden from the user

};};

This declaration describes the interface to the This declaration describes the interface to the user user –– and to the compiler.and to the compiler.A user has access to those parts in the A user has access to those parts in the publicpublic

section, but not those in the section, but not those in the privateprivate part.part.The (private) data is protected.The (private) data is protected.

Applied Programming

The implementation of the class is the actual The implementation of the class is the actual code for the functions. The header file should code for the functions. The header file should also be also be #include#included here.d here.

These functions are preceded by a prefix These functions are preceded by a prefix consisting of the class name and two colons as inconsisting of the class name and two colons as inLinkedList::RemoveLinkedList::Remove()()

We'll see the effect of this prefix on the compiled We'll see the effect of this prefix on the compiled code a little later. code a little later.

Applied Programming

Any such member functions have access to both Any such member functions have access to both the the publicpublic and and privateprivate sections of the class sections of the class ––and can just refer to the variables (and functions) and can just refer to the variables (and functions) by name.by name.

But here is where the power of the class appears.But here is where the power of the class appears.

A class is a declared A class is a declared typetype –– not a variable.not a variable.

Once the type is declared, Once the type is declared, instancesinstances of that type of that type can be declared.can be declared.

Applied Programming

For exampleFor example

LinkedListLinkedList list;list;

declares an instance of the class declares an instance of the class LinkedListLinkedList..

These instances are called These instances are called (class) objects(class) objects..

What does the compiler do with this?What does the compiler do with this?

It sets aside memory for one It sets aside memory for one LinkedListLinkedList data data structure structure –– and names it and names it listlist..

Applied Programming

How much space?How much space?

Enough for the data component Enough for the data component –– both the public both the public and private data.and private data.

There is only one copy of the function code, There is only one copy of the function code, regardless of how many instances of the class.regardless of how many instances of the class.

So our So our LinkedListLinkedList instance requires 4 bytes instance requires 4 bytes for for HeadHead –– and each instance has its own and each instance has its own HeadHead..

Page 4: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

When such an instance of When such an instance of LinkedListLinkedList is is created, its version of created, its version of HeadHead is not initialised. So is not initialised. So we need to call the functionwe need to call the functionLinkedList::InitialiseLinkedList::Initialise();();

To refer to a specific instance we use the To refer to a specific instance we use the instance name as a prefix, followed by instance name as a prefix, followed by .. as inas in

list.Initialiselist.Initialise();();

Does this form seem familiar?Does this form seem familiar?Applied Programming

It looks very much like the way we referred to It looks very much like the way we referred to stream functions likestream functions likecin.eofcin.eof()() and and ofs.closeofs.close()()..

It shows that streams are just instances of a It shows that streams are just instances of a stream class stream class ––

stream objects.stream objects.

(They also look the same as references to (They also look the same as references to structstruct members.)members.)

Applied Programming

So we can callSo we can calllist.Initialiselist.Initialise();();

But C++ helps us more than that.But C++ helps us more than that.

We can set up the values of any private data We can set up the values of any private data automatically when the variable is declared.automatically when the variable is declared.

A special public function is created, called A special public function is created, called a a constructorconstructor..

Applied Programming

Its name is the name of the class.Its name is the name of the class.

And it has no type (not even And it has no type (not even voidvoid).).

So, for our So, for our LinkedListLinkedList class we have the class we have the prototypeprototype

LinkedListLinkedList();();

in our interface.in our interface.

Applied Programming

Its implementation would beIts implementation would be

LinkedList::LinkedListLinkedList::LinkedList()(){{

Head = 0;Head = 0;}}

How do we call it? How do we call it? We don't.We don't.

C++ automatically calls it when we declare an C++ automatically calls it when we declare an instance of our class.instance of our class.(We'll keep (We'll keep Initialise()Initialise() for other uses.)for other uses.)

Applied Programming

For example,For example,

void A()void A(){{

LinkedListLinkedList AlistAlist;;. . .. . .. . .. . .

}}

would generate a call to the constructor.would generate a call to the constructor.

We could then proceed to build our linked list We could then proceed to build our linked list called called AlistAlist..

Page 5: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

What happens when we leave the function?What happens when we leave the function?

As As AlistAlist was automatic, C++ frees up space was automatic, C++ frees up space allocated for it allocated for it –– the space for the space for HeadHead..

But what about space we may have dynamically But what about space we may have dynamically allocated?allocated?

We lose contact with it We lose contact with it -- a memory leak.a memory leak.

We want to clean up.We want to clean up.Applied Programming

C++ helps out again.C++ helps out again.

We have the complementary function to a We have the complementary function to a constructor constructor –– a a destructordestructor..

This is a public function called automatically when This is a public function called automatically when a variable's space is freed up so that we can a variable's space is freed up so that we can clean up dynamic memory.clean up dynamic memory.

Note that we don't have to clean up the memory Note that we don't have to clean up the memory for the instance itself.for the instance itself.

Applied Programming

A destructor's name is the name of the class A destructor's name is the name of the class preceded by a tilde ~ as inpreceded by a tilde ~ as in~~LinkedListLinkedList();();

Again no type.Again no type.

The implementation must clean up all The implementation must clean up all dynamic memory.dynamic memory.

Here it is.Here it is.

Applied Programming

LinkedList::~LinkedListLinkedList::~LinkedList()(){{

CustPtrCustPtr tmptmp;;

while (Head != 0)while (Head != 0){{

tmptmp = Head;= Head;Head = Head = HeadHead-->next;>next;delete delete tmptmp;;

}}}}

Applied Programming

Let's look at an example to see the power of Let's look at an example to see the power of classes.classes.

Consider a supermarket with Consider a supermarket with nn checkouts.checkouts.

Each checkout has its own queue.Each checkout has its own queue.

We'll dynamically allocate the queues so that we We'll dynamically allocate the queues so that we do not limit the number do not limit the number nn..SoSoLinkedListLinkedList *checkout;*checkout;intint n;n;

Applied Programming

Ask for the size of the supermarketAsk for the size of the supermarket

coutcout << "How many checkouts? ";<< "How many checkouts? ";cincin >> n;>> n;

Create the required number of checkouts.Create the required number of checkouts.

checkout = new checkout = new LinkedList[nLinkedList[n];];

C++ will call the constructor for each of the C++ will call the constructor for each of the nnentries, which we can refer to asentries, which we can refer to as

checkout[0], . . . checkout[0], . . . checkout[icheckout[i], . . . ], . . .

Page 6: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

Once we have carried out our simulation of the Once we have carried out our simulation of the supermarket, we can then free up our dynamically supermarket, we can then free up our dynamically allocated space byallocated space by

delete [] checkout;delete [] checkout;

which will invoke the destructor for each instance.which will invoke the destructor for each instance.

But wait.But wait.

Remember what a Remember what a LinkedListLinkedList was?was?

Applied Programming

structstruct CustCust; // forward reference; // forward referencetypedeftypedef CustCust* * CustPtrCustPtr;;

structstruct CustCust{{

char name[30];char name[30];intint partysizepartysize;;CustCust *next;*next;

};};

class class LinkedListLinkedList{{

public:public:void Initialise();void Initialise();void void Add(char[],intAdd(char[],int););void void Remove(char[],intRemove(char[],int&);&);

private:private:CustPtrCustPtr Head;Head;

};};

Not suitable for a supermarket queue.Not suitable for a supermarket queue.

Applied Programming

We want to be able to create such abstract data We want to be able to create such abstract data types as linked lists but be able to put any data types as linked lists but be able to put any data we desire into these linked lists.we desire into these linked lists.

We do that with arrays (built into C++).We do that with arrays (built into C++).

Why can't we do it with our own?Why can't we do it with our own?We can.We can.

We construct generalised classes calledWe construct generalised classes calledtemplatestemplates

We'll see these soon.We'll see these soon.Applied Programming

Let's look at another example to illustrate how we Let's look at another example to illustrate how we can define our own abstract can define our own abstract datatypesdatatypes..

Let's create a time type.Let's create a time type.

What will we call it?What will we call it?

How about How about TimeTypeTimeType..

What will it store?What will it store?time of day in hours, minutes & secondstime of day in hours, minutes & seconds

Applied Programming

What operations do we want to be able to do with What operations do we want to be able to do with this type?this type?

set the timeset the timeprint the timeprint the timeincrement the time by a secondincrement the time by a secondcompare two times for equalitycompare two times for equalitydetermine if one time comes before anotherdetermine if one time comes before another

We are not saying how these requirements are to We are not saying how these requirements are to be implemented be implemented –– the user doesn't need to know.the user doesn't need to know.That's an abstract data type.That's an abstract data type.

Applied Programming

Here is a suitable declaration.Here is a suitable declaration.class class TimeTypeTimeType

{{

public:public:

void void Set(int,int,intSet(int,int,int););

void Increment();void Increment();

void Write() const;void Write() const;

boolbool Equals(constEquals(const TimeTypeTimeType&) const;&) const;

boolbool IsBefore(constIsBefore(const TimeTypeTimeType&) const;&) const;

private:private:

intint hours, minutes, seconds;hours, minutes, seconds;

}}

Let's look in some detail.Let's look in some detail.

Page 7: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

The functions The functions Set()Set(), , Increment()Increment() and and Write()Write() don't have an argument indicating what don't have an argument indicating what we are setting, incrementing or writing.we are setting, incrementing or writing.

How does the program know what data to How does the program know what data to manipulate?manipulate?

Because the name of the identifier precedes the Because the name of the identifier precedes the function when it is used.function when it is used.

Applied Programming

Let's create an instance of a Let's create an instance of a TimeTypeTimeType..

TimeTypeTimeType now;now;

This creates space for the data component of the This creates space for the data component of the class class –– currently (and usually) all private.currently (and usually) all private.

Thus there are three pieces of memory called Thus there are three pieces of memory called now.hoursnow.hours, , now.minutesnow.minutes and and now.secondsnow.seconds..

Just like a Just like a structstruct..

Applied Programming

But, unlike a But, unlike a structstruct, these memory locations , these memory locations are are privateprivate. This means that only member . This means that only member functions of the class have access.functions of the class have access.

Thus, a call toThus, a call to

now.Set(13,10,0);now.Set(13,10,0);

would set the three components of the object would set the three components of the object nownow

to the time 13 hours, 10 minutes and 0 seconds.to the time 13 hours, 10 minutes and 0 seconds.

Applied Programming

SimilarlySimilarly

now.Incrementnow.Increment();();

would add one second to would add one second to nownow..

AndAnd

now.Writenow.Write();();

would output the value of would output the value of nownow –– without changing without changing the contents.the contents.But how do we protect this?But how do we protect this?

Applied Programming

By the use of the keyword By the use of the keyword constconst..

Because the instance is not an argument we Because the instance is not an argument we cannot put cannot put constconst in front of it, so we put in front of it, so we put constconst

after the function itself.after the function itself.

So we haveSo we have

void Write() const;void Write() const;

Let's look at the mechanics of this.Let's look at the mechanics of this.Applied Programming

A call of the formA call of the formnow.Set(a,b,cnow.Set(a,b,c););

is converted tois converted toSet(now,a,b,cSet(now,a,b,c););

since the functionsince the functionSet(int,int,intSet(int,int,int););

is actuallyis actuallySet(TimeType&,int,int,intSet(TimeType&,int,int,int););

Page 8: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

The first argument of each function is a reference The first argument of each function is a reference to the instance.to the instance.

HenceHencevoid Write() const;void Write() const;

becomesbecomes

void void Write(constWrite(const TimeTypeTimeType&);&);

with all the protection usually afforded.with all the protection usually afforded.Applied Programming

Such functions which only look at the private data Such functions which only look at the private data of a class are calledof a class are called

observer observer oror accessoraccessor functionsfunctions(Those that change the contents are called(Those that change the contents are called

mutatormutator functions)functions)But what if we want to access the private data of But what if we want to access the private data of another instance, for example, to compare their another instance, for example, to compare their values?values?We pass it as an argument as inWe pass it as an argument as in

boolbool Equals(constEquals(const TimeTypeTimeType&) const;&) const;

Applied Programming

What happened to the private nature of the data?What happened to the private nature of the data?

We are looking at it from another instance of the We are looking at it from another instance of the same class.same class.

SoSoboolbool Equals(constEquals(const TimeTypeTimeType&) const;&) const;

gets one instance via the name before the gets one instance via the name before the function and the other via the argument.function and the other via the argument.

Applied Programming

Here's an example.Here's an example.

TimeTypeTimeType time1, time2;time1, time2;

if (time1.Equals(time2))if (time1.Equals(time2))coutcout << "time1 equals time2<< "time1 equals time2\\n";n";

This is like a binary operator (==) getting its left This is like a binary operator (==) getting its left operand from before the operand from before the .. and the second and the second operand from the argument.operand from the argument.

This is actually how operators are done, as we This is actually how operators are done, as we shall soon see.shall soon see.

Applied Programming

We've now got an interface for the class, stored in We've now got an interface for the class, stored in TimeType.hTimeType.h. Let's now look at the . Let's now look at the implementation, to go in implementation, to go in TimeType.cppTimeType.cpp..

void void TimeType::Set(intTimeType::Set(int hrs, hrs, intint mins,mins,intint secs)secs)

{{hours = hrs;hours = hrs;minutes = mins;minutes = mins;seconds = secs;seconds = secs;

}}

We just refer to the private data by name.We just refer to the private data by name.Applied Programming

This is just some newfangled way of data hiding. This is just some newfangled way of data hiding. Can't we do better?Can't we do better?

Sure. We can ensure that the value of a Sure. We can ensure that the value of a TimeTypeTimeType is always valid.is always valid.

What if the hours to be set exceeds 23, or the What if the hours to be set exceeds 23, or the seconds is negative?seconds is negative?

There are varying levels of protection, each There are varying levels of protection, each requiring differing levels of intervention.requiring differing levels of intervention.

Page 9: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

Level 1Level 1

Whatever is asked to be stored is stored.Whatever is asked to be stored is stored.(no protection (no protection -- just data hiding)just data hiding)

Level 2Level 2

Adjust the values passed so that the resulting Adjust the values passed so that the resulting stored values are valid. stored values are valid.

Applied Programming

Here's how. Precede the store withHere's how. Precede the store with

if (secs > 59) // assume nonif (secs > 59) // assume non--negativenegative{{

mins += secs/60;mins += secs/60;secs %= 60;secs %= 60;

}}if (mins > 59) // also hereif (mins > 59) // also here{{

hrs += mins/60;hrs += mins/60;mins %= 60;mins %= 60;

}}hrs %= 24; // and againhrs %= 24; // and again

Applied Programming

Level 3Level 3any invalid value is rejected, with an error any invalid value is rejected, with an error message printed and program terminatedmessage printed and program terminated

if (secs < 0 || secs > 59 ||if (secs < 0 || secs > 59 ||

mins < 0 || mins > 59 ||mins < 0 || mins > 59 ||

hrs < 0 || hrs > 23)hrs < 0 || hrs > 23)

{{

cerrcerr << "Illegal time value<< "Illegal time value\\n.";n.";

exit(1); // bad value exitexit(1); // bad value exit

}}

The header The header cstdlibcstdlib should be included for the should be included for the exit()exit() function.function.

Applied Programming

Level 4Level 4any invalid value causes an any invalid value causes an exceptionexception, just like , just like overflows, underflows and divisions by zero in the overflows, underflows and divisions by zero in the builtbuilt--in in datatypesdatatypes..

Exception handling is a very important part of Exception handling is a very important part of C++, but will not be covered here.C++, but will not be covered here.

We could also have the function return an error We could also have the function return an error code, so that the calling program can handle the code, so that the calling program can handle the failure of the function.failure of the function.

Applied Programming

We will use levels 1 to 3. Let's move on.We will use levels 1 to 3. Let's move on.void void TimeType::IncrementTimeType::Increment()(){{

seconds++;seconds++;if (seconds == 60)if (seconds == 60){{

seconds = 0;seconds = 0;minutes++;minutes++;if (minutes == 60)if (minutes == 60){{

minutes = 0;minutes = 0;hours++;hours++;if (hours == 24) hours = 0;if (hours == 24) hours = 0;

}}}}

}}Applied Programming

boolbool TimeType::Equals(constTimeType::Equals(const TimeTypeTimeType& t) const& t) const

{{

return (hours == return (hours == t.hourst.hours

&& minutes == && minutes == t.minutest.minutes

&& seconds == && seconds == t.secondst.seconds););

}}

boolbool TimeType::IsBefore(constTimeType::IsBefore(const TimeTypeTimeType& t) const& t) const

{{

return (hours < return (hours < t.hourst.hours

|| (hours == || (hours == t.hourst.hours && minutes < && minutes < t.minutest.minutes))

|| (hours == || (hours == t.hourst.hours && minutes == && minutes == t.minutest.minutes

&& seconds < && seconds < t.secondst.seconds));));

}}

Note how we use the second instance of the Note how we use the second instance of the class, class, tt, via ", via "structstruct--style" reference to the private style" reference to the private members.members.

Page 10: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

boolbool TimeType::Equals(TimeType::Equals(constconst TimeTypeTimeType& t) & t) constconst

{{

return (hours == return (hours == t.hourst.hours

&& minutes == && minutes == t.minutest.minutes

&& seconds == && seconds == t.secondst.seconds););

}}

boolbool TimeType::IsBefore(TimeType::IsBefore(constconst TimeTypeTimeType& t) & t) constconst

{{

return (hours < return (hours < t.hourst.hours

|| (hours == || (hours == t.hourst.hours && minutes < && minutes < t.minutest.minutes))

|| (hours == || (hours == t.hourst.hours && minutes == && minutes == t.minutest.minutes

&& seconds < && seconds < t.secondst.seconds));));

}}

Note how we use the second instance of the Note how we use the second instance of the class, class, tt, via ", via "structstruct--style" reference to the private style" reference to the private members.members. Applied Programming

And finallyAnd finally

void void TimeType::WriteTimeType::Write() const() const{{//// time is output in the form HH:MM:SStime is output in the form HH:MM:SS

if (hours < 10) if (hours < 10) coutcout << '0';<< '0';coutcout << hours << ':';<< hours << ':';if (minutes < 10) if (minutes < 10) coutcout << '0';<< '0';coutcout << minutes << ':';<< minutes << ':';if (seconds < 10) if (seconds < 10) coutcout << '0';<< '0';coutcout << seconds;<< seconds;

}}

Applied Programming

One of the unwritten preconditions to all the One of the unwritten preconditions to all the functions other than functions other than Set()Set() is that, before a is that, before a reference to any instance of this class can be reference to any instance of this class can be made, a call to made, a call to Set()Set() is required. This is is required. This is because we have yet to provide a class because we have yet to provide a class constructor.constructor.

So let's do it.So let's do it.

Applied Programming

For For TimeTypeTimeType, a constructor might set time to 0., a constructor might set time to 0.

So addSo addTimeTypeTimeType();();

to the definition, andto the definition, and

TimeType::TimeTypeTimeType::TimeType()(){{

hours = minutes = seconds = 0;hours = minutes = seconds = 0;}}

to the implementation.to the implementation.

Applied Programming

This is called a This is called a default constructordefault constructor, as it provides , as it provides no userno user--settable initial value.settable initial value.

NowNowTimeTypeTimeType deadline;deadline;

will allocate the space and set will allocate the space and set deadlinedeadline to to represent time 00:00:00.represent time 00:00:00.

If we don't provide a default constructor, C++ If we don't provide a default constructor, C++ does (but with no initialisation).does (but with no initialisation).

Applied Programming

Arrays of classes cannot be declared without a Arrays of classes cannot be declared without a default constructor.default constructor.

TimeTypeTimeType* * starttimestarttime;;

starttimestarttime = new TimeType[7];= new TimeType[7];

creates and initialises 7 instances.creates and initialises 7 instances.

But what if we want to give a different initial But what if we want to give a different initial value?value?

We define a different constructor.We define a different constructor.

Page 11: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

TimeType(int,int,intTimeType(int,int,int););

with implementationwith implementation

TimeType::TimeType(intTimeType::TimeType(int h, h, intint m, m, intint s)s){{

hours = h;hours = h;minutes = m;minutes = m;seconds = s;seconds = s;

}}

Hey! Don't we then have two functions with the Hey! Don't we then have two functions with the same name?same name?Yes Yes –– with different arguments.with different arguments.

Applied Programming

So nowSo now

TimeTypeTimeType start(10,20,30);start(10,20,30);

will create the variable and set its value to will create the variable and set its value to 10:20:30.10:20:30.

We can eliminate that proviso for We can eliminate that proviso for Set()Set() to be to be called before use of any instance of this type. called before use of any instance of this type.

Set()Set() still does have its uses.still does have its uses.

Applied Programming

TimeTypeTimeType doesn't need a destructor (what would doesn't need a destructor (what would we do in it?) so we let C++ do all the destroying.we do in it?) so we let C++ do all the destroying.

What can we do with objects?What can we do with objects?

Apart from declaring them, calling functions using Apart from declaring them, calling functions using them and dynamically allocating them?them and dynamically allocating them?

Well, lots.Well, lots.

Applied Programming

Copying objectsCopying objectsIn C++ this occurs in two forms:In C++ this occurs in two forms:

explicitexplicit –– the programmer specifies that a the programmer specifies that a particular object's values are to be transferred to particular object's values are to be transferred to the memory of another objectthe memory of another object

Applied Programming

Copying objectsCopying objectsIn C++ this occurs in two forms:In C++ this occurs in two forms:

explicitexplicit –– the programmer specifies that a the programmer specifies that a particular object's values are to be transferred to particular object's values are to be transferred to the memory of another object the memory of another object –– assignmentassignment

implicitimplicit –– the compiler makes a copy of the the compiler makes a copy of the contents of an object into a new memory location contents of an object into a new memory location of the same typeof the same type

Applied Programming

For For structsstructs, we found that assignment was , we found that assignment was practically the only operator that worked.practically the only operator that worked.

Since classes are very similar, assignment also Since classes are very similar, assignment also works here.works here.

SoSoTimeTypeTimeType t1, t2;t1, t2;

t1.Set(10,20,30);t1.Set(10,20,30);t2 = t1;t2 = t1;

Page 12: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

OK.OK.It's time we said what the similarities between It's time we said what the similarities between structsstructs and classes are.and classes are.

When we putWhen we putclass Cclass C

{{

anything after that is private, unless the keyword anything after that is private, unless the keyword publicpublic appears.appears.

For For structsstructs it is the reverse. it is the reverse. Applied Programming

structstruct SS{{........

specifies all things after the specifies all things after the {{ are publicare public–– unless the word unless the word privateprivate appears.appears.

In essence In essence structsstructs and classes are the same!!!and classes are the same!!!

BUT, we usually use BUT, we usually use structstruct for those types with for those types with all public data (and possibly functions).all public data (and possibly functions).

Applied Programming

Now back to copying.Now back to copying.

Since an Since an assigmentassigment just copies the data for an just copies the data for an instance, no dynamic data is copied. instance, no dynamic data is copied.

This is called This is called shallow copyingshallow copying..

Thus, if we create two linked listsThus, if we create two linked listsLinkedListLinkedList list1, list2;list1, list2;

then add some items to then add some items to list1list1, and then, and thenlist2 = list1;list2 = list1;

we get a copy of only the we get a copy of only the HeadHead.. Applied Programming

Thus Thus list2list2 would be the same linked list, but would be the same linked list, but would just have a pointer to the actual items.would just have a pointer to the actual items.

So if the head item were removed from So if the head item were removed from list1list1, , list2list2 would still point at it.would still point at it.

A A dangling pointerdangling pointer..

We might prefer to copy all the data, making We might prefer to copy all the data, making copies of the nodes of the linked list.copies of the nodes of the linked list.

Applied Programming

This is called This is called deep copyingdeep copying..

We provide another class function to C++ so that We provide another class function to C++ so that it is called whenever a copy is to be made.it is called whenever a copy is to be made.

This form of implicit copying is required not just This form of implicit copying is required not just when an assignment is made.when an assignment is made.

Let's leave the assignment operation for a Let's leave the assignment operation for a moment and look at the other time that such moment and look at the other time that such copying is needed.copying is needed.

Applied Programming

When we pass an object by value to a function or When we pass an object by value to a function or have an object being the return value for a have an object being the return value for a function, an implicit copy is also carried out.function, an implicit copy is also carried out.

The difference here is that the copy is made to a The difference here is that the copy is made to a new memory location.new memory location.

A A copy constructorcopy constructor is the class function used by is the class function used by C++ in cases other than assignment.C++ in cases other than assignment.

Page 13: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

It looks the same as the previous constructors It looks the same as the previous constructors except that it has an argument of reference type except that it has an argument of reference type of the class.of the class.

It must perform all the usual tasks that a It must perform all the usual tasks that a constructor does (allocate memory, initialise) but constructor does (allocate memory, initialise) but also must transfer the values of its argument to also must transfer the values of its argument to the class instance.the class instance.

So let's look at the complete set.So let's look at the complete set.Applied Programming

class class aClassaClass{{

. . .. . .//// default constructordefault constructor

aClassaClass();();//// standard constructorstandard constructor

aClassaClass(..,..,..); (..,..,..); //// copy constructorcopy constructor

aClass(constaClass(const aClassaClass&); &); . . .. . .

};};

We'll see the use of the copy constructor later. We'll see the use of the copy constructor later.

Applied Programming

Here's Here's TimeTypeTimeType's's..TimeType::TimeType(constTimeType::TimeType(const TimeTypeTimeType&&

otherTimeotherTime)){{

hours = hours = otherTime.hoursotherTime.hours;;minutes = minutes = otherTime.minutesotherTime.minutes;;seconds = seconds = otherTime.secondsotherTime.seconds;;

}}

See how simple this is.See how simple this is.That's why it isn't needed for this class.That's why it isn't needed for this class.

The assignment operator is coming.The assignment operator is coming.Applied Programming

Let's look at operators in general.Let's look at operators in general.

Many of C++'s builtMany of C++'s built--in operators arein operators arepolymorphicpolymorphic..

They designate the same general operation on They designate the same general operation on different types.different types.

We can reWe can re--use almost all the builtuse almost all the built--in operators for in operators for our own our own ADTsADTs..

This is called This is called operator overloadingoperator overloading..

Applied Programming

Consider the public function Consider the public function Equals()Equals() for for our class our class TimeTypeTimeType..

Recall thatRecall thattime1.Equals(time2)time1.Equals(time2)

is is truetrue if if time1time1 and and time2time2 are equal.are equal.

Wouldn't this be more natural?Wouldn't this be more natural?

time1 == time2time1 == time2

Well, we can provide this.Well, we can provide this.Applied Programming

A warningA warning

The concept of operator overloading is like The concept of operator overloading is like opening Pandora's Box.opening Pandora's Box.

There's no going back.There's no going back.

Provide one operator and users will assume Provide one operator and users will assume they're all available.they're all available.

So consider this step carefully.So consider this step carefully.

Page 14: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

When a binary operator, say When a binary operator, say •• (representing one (representing one of the builtof the built--ins) is encountered in the code ins) is encountered in the code of a of a C++ program, the compiler generates a call to a C++ program, the compiler generates a call to a function named function named operatoroperator•• with one argument with one argument ––the right operand the right operand –– while the left operand is the while the left operand is the class instance.class instance.

SoSo a + ba + b would becomewould become

a.operator+(ba.operator+(b))

Applied Programming

SimilarlySimilarlya == ba == b

becomesbecomesa.operatora.operator==(b)==(b)

Thus, for our own Thus, for our own ADTsADTs to use these operators, to use these operators, we provide the requisite functions. we provide the requisite functions. So, all we have to do for So, all we have to do for TimeTypeTimeType is replaceis replace

boolbool TimeType::Equals(constTimeType::Equals(const TimeTypeTimeType& t) const& t) const

byby

boolbool TimeType::operatorTimeType::operator==(const ==(const TimeTypeTimeType& t) const & t) const

Applied Programming

SimilarlySimilarlyboolbool TimeType::operatorTimeType::operator<(const <(const TimeTypeTimeType& & r_opr_op) const) const{{

return (hours < return (hours < r_op.hoursr_op.hours|| (hours == || (hours == r_op.hoursr_op.hours&& minutes < && minutes < r_op.minutesr_op.minutes))|| (hours == || (hours == r_op.hoursr_op.hours

&& minutes == && minutes == r_op.minutesr_op.minutes

&& seconds < && seconds < r_op.secondsr_op.seconds));));

}}

provides the operator provides the operator <<..

This is just This is just IsBeforeIsBefore()() with the more meaningful with the more meaningful r_opr_op instead of instead of tt..

Applied Programming

We can also provide We can also provide ++ bybyconst const TimeTypeTimeType TimeType::operatorTimeType::operator++

(const (const TimeTypeTimeType& & r_opr_op) const) const{{

TimeTypeTimeType temp = temp = r_opr_op;;

temp.hourstemp.hours += hours;+= hours;temp.minutestemp.minutes += minutes;+= minutes;temp.secondstemp.seconds += seconds;+= seconds;

//// code here to make values within rangecode here to make values within rangereturn temp;return temp;

}}

Applied Programming

We can also provide We can also provide ++ bybyconst const TimeTypeTimeType TimeType::operatorTimeType::operator++

(const (const TimeTypeTimeType& & r_opr_op) const) const{{

TimeTypeTimeType temp = temp = r_opr_op;;

temp.hourstemp.hours += hours;+= hours;temp.minutestemp.minutes += minutes;+= minutes;temp.secondstemp.seconds += seconds;+= seconds;

//// code here to make values within rangecode here to make values within rangereturn temp;return temp;

}}

Whoops Whoops -- we need an assignment operator.we need an assignment operator.(No. This is just initialisation.)(No. This is just initialisation.)We'll explain the first We'll explain the first constconst soon.soon. Applied Programming

The operator we just provided will add two The operator we just provided will add two TimeTypeTimeTypess together.together.

What about adding an integer number of seconds What about adding an integer number of seconds to a time?to a time?

Another operator!! Another Another operator!! Another ++!!!!!!

const const TimeTypeTimeType TimeType::operator+(intTimeType::operator+(int r_opr_op) const) const{{

TimeTypeTimeType temp(hours,minutes,seconds+r_optemp(hours,minutes,seconds+r_op););//// code here to make values within rangecode here to make values within range

return temp;return temp;}}

Page 15: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

So now we can saySo now we can say

TimeTypeTimeType t1(1,2,3), t2;t1(1,2,3), t2;t2 = t1 + 10;t2 = t1 + 10;

BUT we cannot sayBUT we cannot say

t2 = 10 + t1t2 = 10 + t1

as this has an as this has an intint left operand and left operand and TimeTypeTimeType

right operand.right operand.

See how complex this gets!See how complex this gets! Applied Programming

So, what do we need to be able to add a So, what do we need to be able to add a TimeTypeTimeType to an to an intint and get a and get a TimeTypeTimeType??

We need an We need an operator+operator+ function with an function with an intint as as its left operand and a its left operand and a TimeTypeTimeType as its right as its right operand.operand.

We needWe needconst const TimeTypeTimeType operator+(constoperator+(const TimeTypeTimeType&);&);

in the in the intint classclass

Applied Programming

So, what do we need to be able to add a So, what do we need to be able to add a TimeTypeTimeType to an to an intint and get a and get a TimeTypeTimeType??

We need an We need an operator+operator+ function with an function with an intint as as its left operand and a its left operand and a TimeTypeTimeType as its right as its right operand.operand.

We needWe needconst const TimeTypeTimeType operator+(constoperator+(const TimeTypeTimeType&);&);

in the in the intint class class –– but with access to the internals but with access to the internals of of TimeTypeTimeType!!!!!!

Applied Programming

It is not likely that such a function would exist for It is not likely that such a function would exist for intint, nor should it., nor should it.

C++ provides an alternate method of providing C++ provides an alternate method of providing operator overloading.operator overloading.

const const TimeTypeTimeType operator+(int,constoperator+(int,const TimeTypeTimeType&);&);

where the two operands are explicitly listed as where the two operands are explicitly listed as arguments.arguments.

But it still needs access to But it still needs access to TimeTypeTimeType..

Applied Programming

We can place this function We can place this function with(inwith(in) the class ) the class TimeTypeTimeType but not as a member function.but not as a member function.

We call it a We call it a friendfriend of the class.of the class.

The prototype must be preceded with the The prototype must be preceded with the keyword keyword friendfriend..

As this is neither a As this is neither a publicpublic nor nor privateprivate

member function it is placed first within the class.member function it is placed first within the class.

Applied Programming

When we write the implementation of a friend, we When we write the implementation of a friend, we do not put the keyword in front of it.do not put the keyword in front of it.

Nor do we place the Nor do we place the class::class:: before it.before it.

And we have to reference the members of the And we have to reference the members of the instance explicitly.instance explicitly.

Here is a suitable implementation.Here is a suitable implementation.

Page 16: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

const const TimeTypeTimeType operator+(intoperator+(int l_opl_op,,const const TimeTypeTimeType& & r_opr_op))

{{TimeTypeTimeType temp(r_op.hourstemp(r_op.hours, ,

r_op.minutesr_op.minutes, , r_op.seconds+l_opr_op.seconds+l_op););//// code here to make values within rangecode here to make values within range

return temp;return temp;}}

Applied Programming

We said a few slides back that we regularly need We said a few slides back that we regularly need an assignment operator. Let's make one.an assignment operator. Let's make one.

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return *this;return *this;}}

Very similar to the copy constructor.Very similar to the copy constructor.

Applied Programming

The function performs the copy from the source The function performs the copy from the source instance instance fromfrom to the current object, as into the current object, as inhours = hours = from.hoursfrom.hours;;minutes = minutes = from.minutesfrom.minutes;;seconds = seconds = from.secondsfrom.seconds;;

So why is this function not So why is this function not voidvoid??

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return *this;return *this;}}

Applied Programming

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return *this;return *this;}}

Because assignments have a value.Because assignments have a value.

So we must return a reference to the instance we So we must return a reference to the instance we have just copied to.have just copied to.

Applied Programming

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return return *this*this;;}}

Because assignments have a value.Because assignments have a value.

So we must return a reference to the instance we So we must return a reference to the instance we have just copied to.have just copied to.

Applied Programming

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return return *this*this;;}}

We are returning the dereference of We are returning the dereference of thisthis

–– which is the address of the current instance.which is the address of the current instance.

Page 17: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

TimeTypeTimeType&& TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return return *this*this;;}}

We are returning the dereference of We are returning the dereference of thisthis

–– which is the address of the current instance.which is the address of the current instance.

We can return a reference.We can return a reference.

Applied Programming

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return *this;return *this;}}

So now we can saySo now we can say

t1 = t2 = t3;t1 = t2 = t3;

So what's so special about So what's so special about == ??

Beware of dynamic data.Beware of dynamic data.

Applied Programming

TimeTypeTimeType& & TimeType::operatorTimeType::operator==(const (const TimeTypeTimeType& from)& from)

{{//// code here to copy the members of fromcode here to copy the members of from//// to this objectto this object

return *this;return *this;}}

If we are actually doingIf we are actually doingt1 = t1 = t1t1;;

then we have to avoid freeing up existing then we have to avoid freeing up existing dynamic data of the current instance.dynamic data of the current instance.So we need tests for So we need tests for this == &fromthis == &from

Applied Programming

The other concern is that the instance we are The other concern is that the instance we are copying to may already have dynamic data copying to may already have dynamic data attached.attached.

If so, we do not want to lose contact with it, at If so, we do not want to lose contact with it, at least not before we delete it.least not before we delete it.

So, there must be some code to clean up So, there must be some code to clean up dynamic data of the destination instance, dynamic data of the destination instance, if there is any.if there is any.

Applied Programming

Unary operators such as ++ and Unary operators such as ++ and ---- can also be can also be overloaded.overloaded.

We'll leave these to later courses (or your own We'll leave these to later courses (or your own reading).reading).

Be aware that these have complications.Be aware that these have complications.

Again Again –– watch for the Pandora's Box.watch for the Pandora's Box.

Applied Programming

There are several other operators which are There are several other operators which are special.special.

<<<< insertion operator for streamsinsertion operator for streams

>>>> extraction operatorextraction operator

We need to overload these, but they are We need to overload these, but they are operators of another class.operators of another class.

What class?What class?

Page 18: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

Well, we've used the alreadyWell, we've used the already--defined streams defined streams cincin, , coutcout and and cerrcerr..

Just instances of classes.Just instances of classes.

We've made our own streams usingWe've made our own streams usingifstreamifstream, , ofstreamofstream (and (and fstreamfstream).).

Instances of these classes.Instances of these classes.

But they're not the ones.But they're not the ones.Applied Programming

C++ provides a mechanism for a hierarchy of C++ provides a mechanism for a hierarchy of classes where each level of the hierarchy inherits classes where each level of the hierarchy inherits behaviours from its ancestors in the family tree.behaviours from its ancestors in the family tree.

This process is called This process is called inheritanceinheritance..

It is the foundation of objectIt is the foundation of object--oriented oriented programming using C++.programming using C++.

We'll introduce inheritance later.We'll introduce inheritance later.

Applied Programming

For now, we only need to know that there are two For now, we only need to know that there are two stream classes providing the base for our known stream classes providing the base for our known stream classes.stream classes.

They areThey areistreamistream for inputfor input

andandostreamostream for outputfor output

We can now see that the functions such as We can now see that the functions such as cin.getcin.get()(), , cin.eofcin.eof()() and and cout.putcout.put()()

are just public functions.are just public functions.Applied Programming

What is more important is that the two operators What is more important is that the two operators <<<< and and >>>> are just operators defined for streams.are just operators defined for streams.

That is, they are just functions.That is, they are just functions.For example, in For example, in ostreamostream we havewe have

ostreamostream& operator<<(const type&);& operator<<(const type&);

or the or the friendfriend equivalent, for each equivalent, for each typetype of of builtbuilt--in.in.

But they belong to the class But they belong to the class ostreamostream..

Applied Programming

We can, however, write a We can, however, write a friendfriend functionfunction

friend friend ostreamostream& operator<<(& operator<<(ostreamostream&,&,const const TimeTypeTimeType&);&);

and place this in the declaration of our class and place this in the declaration of our class TimeTypeTimeType, before the , before the publicpublic or or privateprivate parts parts as inas inclass class TimeTypeTimeType{{

friend ...friend ...

Here's what the implementation looks like.Here's what the implementation looks like.Applied Programming

ostreamostream& operator<<(& operator<<(ostreamostream& & osos, const , const TimeTypeTimeType& time)& time){{//// time is output in the form HH:MM:SStime is output in the form HH:MM:SS

if (if (time.hourstime.hours < 10)< 10)osos << '0';<< '0';

osos << << time.hourstime.hours << ':';<< ':';if (if (time.minutestime.minutes < 10)< 10)

osos << '0';<< '0';osos << << time.minutestime.minutes << ':';<< ':';if (if (time.secondstime.seconds < 10)< 10)

osos << '0';<< '0';osos << << time.secondstime.seconds;;return return osos;;

}}

There is no There is no friendfriend prefix here in the prefix here in the implementation.implementation.

Page 19: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

ostreamostream& operator<<(& operator<<(ostreamostream& & osos, const , const TimeTypeTimeType& time)& time){{//// time is output in the form HH:MM:SStime is output in the form HH:MM:SS

if (if (time.hourstime.hours < 10)< 10)osos << '0';<< '0';

osos << << time.hourstime.hours << ':';<< ':';if (if (time.minutestime.minutes < 10)< 10)

osos << '0';<< '0';osos << << time.minutestime.minutes << ':';<< ':';if (if (time.secondstime.seconds < 10)< 10)

osos << '0';<< '0';osos << << time.secondstime.seconds;;return return osos;;

}}

The The TimeTypeTimeType is an argument here so member is an argument here so member data is completely specified.data is completely specified.

Applied Programming

ostreamostream& operator<<(& operator<<(ostreamostream& & osos, const , const TimeTypeTimeType& time)& time){{//// time is output in the form HH:MM:SStime is output in the form HH:MM:SS

if (if (time.hourstime.hours < 10)< 10)osos << '0';<< '0';

osos << << time.hourstime.hours << ':';<< ':';if (if (time.minutestime.minutes < 10)< 10)

osos << '0';<< '0';osos << << time.minutestime.minutes << ':';<< ':';if (if (time.secondstime.seconds < 10)< 10)

osos << '0';<< '0';osos << << time.secondstime.seconds;;return return osos;;

}}

And we return a reference to the stream.And we return a reference to the stream.

Applied Programming

Now we don't need the Now we don't need the Write()Write() member member function (although function (although <<<< could call it).could call it).

We can just sayWe can just say

TimeTypeTimeType t(10,20,30);t(10,20,30);

coutcout << "The time is " << t << << "The time is " << t << endlendl;;

and getand get

The time is 10:20:30The time is 10:20:30

Applied Programming

OK. We're on a roll. Let's try input.OK. We're on a roll. Let's try input.

We'll have a function likeWe'll have a function like

friend friend istreamistream& operator>>(& operator>>(istreamistream&, type&);&, type&);

for each builtfor each built--in.in.

What does it have to do?What does it have to do?

Convert text characters to the type.Convert text characters to the type.

Applied Programming

Suppose we want to input Suppose we want to input TimeTypeTimeType in exactly in exactly the same way as we are outputting them the same way as we are outputting them –– three three integers separated by :integers separated by :

istreamistream& operator>>(& operator>>(istreamistream& is,& is,

TimeTypeTimeType& time)& time){{

char temp;char temp;

is >> is >> time.hourstime.hours;;is >> temp; // should be a :is >> temp; // should be a :is >> is >> time.minutestime.minutes;;is >> temp; // another :is >> temp; // another :is >> is >> time.secondstime.seconds;;return is;return is;

}}Applied Programming

Of course, this assumes that input is correct.Of course, this assumes that input is correct.

A final version would require error checking.A final version would require error checking.

Should an error occur, error flags should be Should an error occur, error flags should be turned on and the stream should not be returned turned on and the stream should not be returned –– just as in the usual extractors.just as in the usual extractors.

We'll leave this for future study.We'll leave this for future study.

Page 20: C++ Programming University of Wollongong 2011 - Classes

Applied Programming

OK. Let's now say something about those OK. Let's now say something about those constconst

terms on the operator functions, such asterms on the operator functions, such as

constconst TimeTypeTimeType TimeType::operatorTimeType::operator++(const (const TimeTypeTimeType& & r_opr_op) const) const

If If aa and and bb were both were both TimeTypeTimeType, then so is, then so is

a + ba + b

This means we can then sayThis means we can then say

coutcout << a + b << << a + b << endlendl; ;

Applied Programming

But what if we have a But what if we have a mutatormutator function such as function such as SetSet, then we could write, then we could write

(a+b).Set(10,25,30);(a+b).Set(10,25,30);

Not if it were not a Not if it were not a constconst ..