TopStandard Template Library

Standard Template Library

Generic functions

C++ supports many generic functions. For example:

    Iterator find(Iterator begin, Iterator end, const Object & x)
    Iterator find_if(Iterator begin, Iterator end, Predicate pred)

In the last, the function returns an iterator pointing to the first element satisfying pred. Both return end if nothing is found.

The following example from the book shows its use. Suppose we wish to find the first occurrence of a string with fixed length len. We can write:

    template <int len>
    class StringLength {
    public:
       bool operator()(const string & s) {
          return s.length() == len;
       }
    }
    
    itr = find_if(v.begin(), v.end(), StringLength<9>());

Note that StringLength.operator()(s) is equivalent to StringLength(s).

We can also use generic sort routines. For example:

    template<class RandomAccessIterator>
    void sort(RandomAccessIterator first, RandomAccessIterator last)
    
    template<class RandomAccessIterator, class Compare>
    void sort(RandomAccessIterator first, RandomAccessIterator last,
              Compare comp);

Uses a comparator to sort the list. As usual it goes from [first, last), i.e., last is not included in the range sorted. It uses operator(...,...). Note that rather than using the Comparator you can just define operator<(...,...) for the type.

There are many, many more of these, and if you expect to be doing a lot of C++ programming you should pick up a book on the STL.

C++ I/O

As you can see in the book, there are lots of ins and outs of C++ I/O. We'll only worry about the very basics here.

When bad things happen to good I/O

You can ask a stream for its state with eof (already hit eof, fail (unsuccessful operation, like reading char as an int, bad (stream is corrupted), or good (none of the other error conditions were raised). Note that if you don't ask after an I/O operation, execution will continue as if it succeeded. No exceptions are thrown.

Here is an example of its use:

    cin >> x;
    while (!cin.eof()) {
       // do something with x
       cin >> x;
    }

A short cut would be

    while (cin >> x) {
       // do something with x
    }

as cin >> x returns true if no error conditions are set, though of course no error recovery would be attempted. Note that when bad things happen, the error state is true until you explicitly clear it: cin.clear();

Problems with cin: If you write

    cin >> x;

then cin will skip leading white space and then read in the string up to the next white space. It will not consume "
n" at the end of a line. If you want to read the next full line, you will need to get rid of the "
n". Thus you must explicitly read that and throw it away. See averageWError.cpp.

Note that you can read a character at a time with "get()".

You can also peek ahead at a character that hasn't officially been read yet. See stringIO.cpp, though it doesn't work if there are spaces at the end of the line.

Output is fairly straightforward, though it takes some work to set up columns using setw, etc., though you must import the library iomanip.

Opening a file is straightforward using strings:

    ifstream file(``myfile.dat'');  // input file
    ofstream file(``yourfile.dat''); // output file

However, if you use a string variable then you must convert it to a primitive C-style array of characters using myString.c_str().

Abstract classes

Recall that an abstract class is one with at least one abstract method, where abstract methods are not provided with method bodies. In Java we write: C m(...);. In C++ we write virtual C m(...) = 0;. A class is said to be purely abstract if all of its methods are abstract.

While C++ supports multiple inheritance, it is considered bad form except when all but one of the superclasses is purely abstract. If a class is purely abstract then it can be treated like an interface.

Final pointers in C++

If you want to see what they have been learning about C++ in HMC CS 70, please go to:

https://www.cs.hmc.edu/twiki/bin/view/CS70Spring2007/ClassNotes
  1. Anything created with new needs to be deleted.
  2. With classes, you need to always provide constructors, (virtual) destructors, and operator=. Make sure they do the right thing. Instance variables are not automatically initialized.
  3. Copy constructors vs. operator=(): When is each called? Copy constructors are called when the target does not yet exist. E.g., C c = d; and C c(d); call the copy constructor, while C c; c = d; calls the 0-argument constructor (if it exists - it blows up otherwise) and then (on assignment) calls operator=. Note that copy constructors are always used with call-by-value! Destructors are run when a variable goes out of scope. But not for pointers!! They are run when delete is executed. If you don't provide constructors at all, then system will write one for you (setting all instance vbles to default values). If no copy constructor, it will write the obvious one. Similarly with operator=.
  4. When emulating Java always use pointers to objects. If you don't, subtyping won't work correctly (i.e., you can't use a subclass object where a superclass is expected).
  5. Use initializers to avoid repeatedly initializing an object. Watch for gratuitous copying of values. Most programmers don't have a good sense when the copy constructors are called.
  6. Avoid arrays wherever possible in favor of vectors. While it is still possible to blow vector bounds, they keep track of their current size.

TopStandard Template Library