Figure 4: Classes derived from DirAdapter provide specific functions to be applied to directories and files

// dir.h

class NamePrinter : public DirAdapter
{
   fstream fout;
public:
   NamePrinter(const string &outfile, char sep = '\\');
   ~NamePrinter() {fout.close();}
   bool 
   processComposite(Directory &dir, const CompositeHandle &ch);
   bool processSimple(Directory &dir, const SimpleHandle &sh);
};

class FileCounter : public DirAdapter
{
   int count;
public:
   FileCounter() : count(0) {}
   // ignore directories
   bool 
   processComposite(Directory &dir, const CompositeHandle &ch)
   {}
   // count files
   bool processSimple(Directory &dir, const SimpleHandle &sh)
   {count++;}
   int getCount() const {return count;}
   void setCount(int n = 0) {count = n;}
};

// dir.cpp

NamePrinter::NamePrinter(const string &outfile, char sep)
   : DirAdapter(sep)
{
   fout.open(outfile.c_str(), ios::out);
   if(!fout)
      throw "can't open output file";
}

bool 
NamePrinter::processComposite(Directory &dir, 
   const CompositeHandle &ch)
{
   cout << ch << "...DIR" << endl;
   fout << ch << "...DIR" << endl;
   return true;
}

bool 
NamePrinter::processSimple(Directory &dir, 
   const SimpleHandle &sh)
{
   cout << sh << "...FILE" << endl;
   fout << sh << "...FILE" << endl;
   return true;
}