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.openmyFile”, 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 stream’s 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 won’t 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 element’s 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

•      Vectors—implemented as a dynamic array

•      Deques—a 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