Inheriting
from STL containers
The
power of instantly creating a sequence of elements is amazing, and it makes you
realize how much time you’ve spent (or rather, wasted) in the past
solving this particular problem. For example, many utility programs involve
reading a file into memory, modifying the file and writing it back out to disk.
One might as well take the functionality in
StringVector.cpp
and package it into a class for later reuse.
Now
the question is: do you create a member object of type
vector,
or do you inherit? A general guideline is to always prefer composition (member
objects) over inheritance, but with the STL this is often not true, because
there are so many existing algorithms that work with the STL types that you may
want your new type to
be
an STL type. So the list of
strings
should
also
be
a
vector,
thus inheritance is desired.
//: C20:FileEditor.h
// File editor tool
#ifndef FILEEDITOR_H
#define FILEEDITOR_H
#include <string>
#include <vector>
#include <iostream>
class FileEditor :
public std::vector<std::string> {
public:
FileEditor(char* filename);
void write(std::ostream& out = std::cout);
};
#endif // FILEEDITOR_H ///:~
Note
the careful avoidance of a global
using
namespace std
statement here, to prevent the opening of the
std
namespace to every file that includes this header.
The
constructor opens the file and reads it into the
FileEditor,
and
write( )
puts the
vector
of
string
onto any
ostream.
Notice in
write( )
that
you can have a default argument for a reference.
The
implementation is quite simple:
//: C20:FileEditor.cpp {O}
#include "FileEditor.h"
#include <fstream>
#include "../require.h"
using namespace std;
FileEditor::FileEditor(char* filename) {
ifstream in(filename);
assure(in, filename);
string line;
while(getline(in, line))
push_back(line);
}
// Could also use copy() here:
void FileEditor::write(ostream& out) {
for(iterator w = begin(); w != end(); w++)
out << *w << endl;
} ///:~
The
functions from
StringVector.cpp
are simply repackaged. Often this is the way classes evolve – you start
by creating a program to solve a particular application, then discover some
commonly-used functionality within the program that can be turned into a class.
The
line numbering program can now be rewritten using
FileEditor:
//: C20:FEditTest.cpp
//{L} FileEditor
// Test the FileEditor tool
#include "FileEditor.h"
#include <sstream>
#include "../require.h"
using namespace std;
int main(int argc, char* argv[]) {
requireArgs(argc, 1);
FileEditor file(argv[1]);
// Do something to the lines...
int i = 1;
FileEditor::iterator w = file.begin();
while(w != file.end()) {
ostringstream ss;
ss << i++;
*w = ss.str() + ": " + *w;
w++;
}
// Now send them to cout:
file.write();
} ///:~
Now
the operation of reading the file is in the constructor:
FileEditor
file(argv[1]);
and
writing happens in the single line (which defaults to sending the output to
cout): The
bulk of the program is involved with actually modifying the file in memory.
Go to CodeGuru.com
Contact: webmaster@codeguru.com
© Copyright 1997-1999 CodeGuru