class GenericTableAlgorithm
{
public:
GenericTableAlgorithm(const string& table);
virtual ~GenericTableAlgorithm();
// Process() returns true if and only if successful.
// It does all the work: a) physically reads
// the table's records, calling Filter() on each
// to determine whether it should be included
// in the rows to be processed; and b) when the
// list of rows to operate upon is complete, calls
// ProcessRow() for each such row.
//
bool Process();
private:
// Filter() returns true if and only if the row should be
// included in the ones to be processed. The
// default action is to return true (to include
// every row).
//
virtual bool Filter( const Record& );
// ProcessRow() is called once per record that
// was included for processing. This is where
// the concrete class does its specialized work.
// (Note: This means every row to be processed
// will be read twice, but assume that that is
// necessary and not an efficiency consideration.)
//
virtual bool ProcessRow( const PrimaryKey& ) =0;
struct GenericTableAlgorithmImpl* pimpl_; // MYOB
};
class MyAlgorithm : public GenericTableAlgorithm
{
// ... override Filter() and ProcessRow() to
// implement a specific operation ...
};
int main()
{
MyAlgorithm a( "Customer" );
a.Process();
}
class Map
{
private:
struct MapImpl;
MapImpl* pimpl_;
};