Overloading operators
Overloading the plus operator
Distance Distance:: operator + (Distance rhs)
{
Distance temp;
temp.feet
= feet + rhs.feet;
temp.inches
= inches + rhs.inches;
if (temp.inches
>=12)
{ temp.inches
-=12;
temp.feet++;
}
return temp;
}
The ostream class
When we overload
the << operator, we must return a reference to an object of type ostream
If we overload << for the
Distance class, it looks like this:
ostream& operator
<< (ostream& s, Distance& d)
{ s << d.feet
<< " feet " << d.inches
<< " inches ";
return s }
Friends
When a function or class is declared a friend to a
class, then it can access that classes private data members
The
keyword friend is placed in front of the function prototype
The istream class
When we overload
the >> operator, we must return a reference to an object of type istream
Overloading the >> operator for the Distance
class
istream& operator >> (istream&
s, Distance& d)
{ cout <<
" \nEnter feet: " ; s >> d.feet;
cout
<< " Enter inches: "; s
>> d.inches;
return s;
}
This function must also be declare a friend to the
Distance class
Templates
Function templates
Used when you want to perform the same operation on
different data types.
The definition of HOW to perform the operation
must be the same for different data types
Two new keywords
template
typename
Suppose you want
to swap two integers
void
swap(int &x, int
&y)
{ int temp
temp = x; x = y; y = temp;}
Now suppose you
want to swap two characters
void
swap(char &x, char &y)
{char temp
temp = x; x = y; y = temp;}
A template to swap any two items; the type is generic
template <typename
T>
void swap(T
&x, T &y)
{T temp
temp = x; x = y; y = temp;}
Instantiating the template function
The template itself has no type associated with
it.
You must tell the
compiler what type you want substituted for the T
i.e. you must make an instance of the template with a
real data type
You instantiate the template function by when
you call it with actual data types
Calling a template function
The call: w = max(x,y,z);
If w, x, y, z
have been declared as integers, the compiler will make a function where int replaces the T
Another call: a = max(b,c,d);
If you call again
with a, b, c, d which have been declared as floats, the compiler will make
another copy, this time substituting float for T
Prototypes for function templates
You can have a
template function prototype
template
<typename T>
T max (T, T, T);
A word on terminology
These are
equivalent:
template <typename
T>
template <class myType>
Templates are a way to generate code
A copy of the function is generated by the compiler for
every type for which the function is called
So the compiler is actually generating code for you.
Note that is not explicitly necessary to tell
the compiler the value for T
It can deduce the type from the call
Templates and overloading
When do you use a template, and when do you overload?
Templates and overloading have different purposes
If the definition
is the same for different data types, you use a template
If you want to
perform similar operations that involve different program logic on
different data types you overload
Class templates
Generally used for data storage (container) classes
If you declare a stack or linked list to work with one
type of data, it only works with that one type
Class templates allow the type to be generic
template<class T>
class Stack
{
.}
Instantiating the class
Classes are instantiated by defining an object
using the template argument
EX Stack<float> s1;
Stack<long> s2;
Exception in C++
Exception concepts
Exceptions are errors that occur at runtime
If they are not handled, they will crash your program
They are a way to separate
the code that deals with error conditions from
the code that executes when there are no errors.
Exceptions use three new keywords
try identifies a code block in which an exception occurs
throw causes an exception condition to be originated
catch identifies a block of code in which the exception is
handled
Exception syntax
The programmer encloses in a try
block the code that may generate an error
The try
block is followed by one or more catch blocks
Each catch block specifies the
type of exception it can handle
It contains the
exception handler for that type of exception
If no handler is found, function terminate is called
which calls function abort
If no exception is thrown, the catch
block is not executed
Specifying an exception class
Often an exception class is created just to have a type
to throw
Catching an exception
Each catch block specifies a type
it can catch, along with an optional parameter name.
When an exception is caught, the code in the catch
block is executed
The catch block must immediately
follow the try block.
After the code in
the catch block is executed, execution continues with the
next statement after the catch block
If an exception is not thrown by code in the try
block (or any function called directly or indirectly in the
try block) the catch block is ignored.
Streams and Files
What are streams
A stream is a general name given to a flow of data
In C++ a stream is represented by an object of
a stream class
We have been using cin and cout as stream objects
Stream basics
A stream is a logical device that either produces
or consumes information
A stream is linked to a physical device by the
I/O system.
This physical
device can be the monitor, keyboard, disk drive, or others
All streams behave in the same way even though they
may be connected to different physical devices
Because all streams behave the same way, the same I/O
functions can operate on virtually any type of physical device
Stream class hierarchy
The ios class is the super class of most stream classes
It has many
member functions which are then inherited by its derived classes
Formatting flags
and manipulators are members of the ios class
The istream and ostream classes are derived from the ios class
The ifstream class is derived from the istream class
The ofstream class is derived from the ostream class
The reason it is
important to know about the hierarchy is so you understand that they have the
same member functions that can be used.
Formatted I/O
There are two conceptually different ways to format
data
You can set
various format status flags defined inside the ios class
You can use special functions called manipulators
Often there is more than one way to do something
Formatting flags of the ios
class
Formatting flags are a set of definitions in the ios class
They act as on/off switches to format output
There are different ways the flags can be set, but all
can be set using the setf( ) and unsetf( ) iso member functions
Example: note
that you must use the scope resolution operator
cout.setf(iso::left);
// left justifies the output
cout >> whatever ;
cout.unsetf(ios::left);
Manipulators
Manipulators are formatting instructions inserted
directly into a stream
endl is an
often used manipulator
Some manipulators have arguments, others do not.
Except for the flags and manipulators you use
regularly, you will
want
to have a reference nearby.
Examples using manipulators
cout << setw(15)
// set next filed width to 15
cout << left; //field
on left, padding on right
cout << right; //
field on right, padding on left;
cout<< setprecision(2); // two
decimal places
cout << scientific; // out
double w/ scientific notation
ostream& operator << (ostream&
s, Person& p)
{
s << setw(20) << left << p.name
<< setw(30)
<< p.address
<< p.phone
<< endl;
}
Detecting end-of-file
The EOF is a signal sent to the program from the
operating system when there is no more data to read
One way to check
for this is:
while (!infile.eof( ))
Another way is:
while (infile.good( ) )
This will check
for any error conditions
Another way is:
while (infile)
This tests the stream
directly. As long as everything isgoing well, this will return a nonzero value.
At eof or any error condition it will return a zero
Opening files
When you declare an object of type ofstream or ifstream along with the file name, the file is opened automatically
If you open a file this way, you accept some defaults
The default for
an ifstream object is to open the file to begin reading at the
beginning of the file
The default for an ofstream object is to overwrite the file
You can change
these defaults using mode bits, used this way
ofstream ofile;
ofile.open(myFile, ios::app);
Mode bits
Closing files
It is not usually necessary to close files explicitly
because they are
closed
automatically when the stream goes out of scope
Their destructors are called and close the file
You may want to use an explicit close( ) every time you close a
file,
without relying on the streams destructor.
If you open a file for reading, then want to write to
it, you must
close
it for reading before opening it for writing.
Writing Objects to files
Lafore does this using the reinterpret_cast operator
The reinterpret_cast tells the compiler I know you wont
like this, but I want to do it anyway
It changes the type of a section of memory without
caring whether it makes sense.
This is an unsafe programming practice, but you can
read about it and use it if you want.
Page 591
The
Standard Template Library
STL Components
Containers
Iterators
These are smart pointers
Algorithms
These are global functions used to process the
elements of containers.
Containers
These are class templates that have member
functions to manage the elements
Two general kinds of containers
Sequence container
These
are collections whose position depends on time and place of insertion
The
position is independent of the elements value
Associative containers
These
are sorted collections
The
actual position of an element depends on its value due to a certain sorting criterion
Iterators
An iterator represents a certain position in a
container
All iterators are defined with these fundamental
operations
Operator ++ step forward to
the next element
Operators = = and != equal and not equal
Operator = the assignment
operator
Operator * dereferences
An iterators is a class nested inside the collection
class template
Container class member functions
All container
classes provide some basic member functions that enable them to use iterators.
begin( )
Returns an iterator that is the beginning position of the first element of the container
end( )
Returns an iterator that is one byte past the end of the elements in the container.
This is also call a past-the-end iterator
size( )
Returns the number of items in the container
empty( )
Returns true
if the container is empty
push_back ( )
Adds an element
to the end of a sequential container
Algorithms
These are global
function templates that operate on containers through iterators
The first two args are a pair of iterators (first, last) marking off the range of elements in the container
over which to operate
Member functions vs. global algorithms
Often a container has a member function that does the
same thing as an algorithm, but with much better performance
An example is the
global remove( ) algorithm
remove( )
reorders the elements by changing their values
The list
container class provides special member functions for all the algorithms that
manipulate elements in the list.
For example,
global sort( ) will not work with list containers, since it requires a random
access iterator. Instead, use the sort(
) member function.
The sequence containers
Vectorsimplemented as a dynamic array
Dequesa double ended queue;
Lists implemented as a doubly linked list
In addition, you
can use strings and ordinary arrays as sequence containers
The vector container--how it is implemented
Implemented as a dynamic array(size depends on
implementation)
To use a vector you must include the header file #include <vector>
Vectors provide good
performance if you insert or delete elements at the end
When you insert
or delete in the middle or beginning, every element behind has to be moved to
another position
Any object that
will be stored in a vector must define a default constructor and the < and = = operations
You can use array
subscripting to access or modify vector elements
No range checking done with [ ]
Use the at( ) member function for range
checking
Deque containers
To use a deque
you must include the header file #include <deque>
Implemented as
dynamic arrays, typically a bunch of individual blocks, growing in opposite
directions
The interface of
vectors and deques is almost the same
Inserting or
deleting at either end of a deque is efficient
Inserting or
deleting in the middle of a deque is
inefficient, but can be done (same as for vectors)
List containers
Implemented as a
doubly linked list
Many special
member functions for inserting, deleting and moving elements. They are faster than the global algorithms
with the same names.
To use a list you must include the header file #include
<list>
Associative containers
Sets & Multisets
These containers
sort their elements automatically according to a certain sorting criterion
The difference is
that multisets allow duplicates; sets do not
Maps & Multimaps
These containers
manage key/value pairs as elements
They also sort
their elements automatically according to some sorting criterion that is used
for the key
The difference is
that maps do not allow duplicates, while multimaps do
Pairs
The class pair is
provided to treat two values as a single unit.
It
has two data members, first and second
It is used by
maps and multimaps to manage their elements
Associative containers
Implemented as balanced
binary search trees (specifically, red-black trees)
Note about Associate containers
To modify the
value of an element, you must remove the old element and insert a new one
If you want to
remove elements from an associative container, you must use the member
functions
Algorithms that
remove elements or that reorder or
modify elements cannot be used with associative containers
Trying will
result in a compiler error
This is because
if they could change the value or position of elements they would not be sorted
anymore