In general, you may not have to supply definitions for all of these virtual functions when designing your own class. For example, if you know that your class will never be used in sorted collections, then you do not need a definition for compareTo(). Nevertheless, it is a good idea to supply definitions for all virtual functions anyway: that's the best way to encourage code reuse!
Here then, is the complete listing for our class Bus:
BUS.H: #ifndef __BUS_H__ #define __BUS_H__ #include <rw/rwset.h> #include <rw/collstr.h> class Bus : public RWCollectable { RWDECLARE_COLLECTABLE(Bus) public: Bus(); Bus(int busno, const RWCString& driver); ~Bus(); // Inherited from class "RWCollectable": Rwspace binaryStoreSize() const; int compareTo(const RWCollectable*) const; RWBoolean isEqual(const RWCollectable*) const; unsigned hash() const; void restoreGuts(RWFile&); void restoreGuts(RWvistream&); void saveGuts(RWFile&) const; void saveGuts(RWvostream&) const; void addPassenger(const char* name); void addCustomer(const char* name); size_t customers() const; size_t passengers() const; RWCString driver() const {return driver_;} int number() const {return busNumber_;} private: RWSet customers_; RWSet* passengers_; int busNumber_; RWCString driver_; }; class Client : public RWCollectable { RWDECLARE_COLLECTABLE(Client) Client(); Client(const char* name); Rwspace binaryStoreSize() const; int compareTo(const RWCollectable*) const; RWBoolean isEqual(const RWCollectable*) const; unsigned hash() const; void restoreGuts(RWFile&); void restoreGuts(RWvistream&); void saveGuts(RWFile&) const; void saveGuts(RWvostream&) const; private: RWCString name_; //ignore other client information for this example }; #endif BUS.CPP: #include "bus.h" #include <rw/pstream.h> #include <rw/rwfile.h> #ifdef __GLOCK__ # include <fstream.hxx> #else # include <fstream.h> #endif RWDEFINE_COLLECTABLE(Bus, 200) Bus::Bus() : busNumber_ (0), driver_ ("Unknown"), passengers_ (rwnil) {} Bus::Bus(int busno, const RWCString& driver) : busNumber_ (busno), driver_ (driver), passengers_ (rwnil) {} Bus::~Bus() { customers_.clearAndDestroy(); delete passengers_; } RWspace Bus::binaryStoreSize() const { RWspace count = RWCollectable::binaryStoreSize() + customers_.recursiveStoreSize() + sizeof(busNumber_) + driver_.binaryStoreSize(); if (passengers_) count += passengers_->recursiveStoreSize(); else count += RWCollectable::nilStoreSize(); return count; } int Bus::compareTo(const RWCollectable* c) const { const Bus* b = (const Bus*)c; if (busNumber_ == b->busNumber_) return 0; return busNumber_ > b->busNumber_ ? 1 : -1; } RWBoolean Bus::isEqual(const RWCollectable* c) const { const Bus* b = (const Bus*)c; return busNumber_ == b->busNumber_; } unsigned Bus::hash() const { return (unsigned)busNumber_; } size_t Bus::customers() const { return customers_.entries(); } size_t Bus::passengers() const return passengers_ ? passengers_->entries() : 0; } void Bus::saveGuts(RWFile& f) const { RWCollectable::saveGuts(f); // Save base class f.Write(busNumber_); // Write primitive directly f << driver_ << customers_; // Use Rogue Wave provided versions f << passengers_; // Will detect nil pointer automatically } void Bus::saveGuts(RWvostream& strm) const { RWCollectable::saveGuts(strm); // Save base class strm << busNumber_; // Write primitives directly strm << driver_ << customers_; // Use Rogue Wave // provided versions strm << passengers_; // Will detect nil pointer automatically } void Bus::restoreGuts(RWFile& f) { RWCollectable::restoreGuts(f); // Restore base class f.Read(busNumber_); // Restore primitive f >> driver_ >> customers_; // Uses Rogue Wave // provided versions delete passengers_; // Delete old RWSet f >> passengers_; // Replace with a new one } void Bus::restoreGuts(RWvistream& strm) { RWCollectable::restoreGuts(strm); // Restore base class strm >> busNumber_ >> driver_ >> customers_; delete passengers_; // Delete old RWSet strm >> passengers_; // Replace with a new one } void Bus::addPassenger(const char* name) { Client* s = new Client(name); customers_.insert( s ); if (!passengers_) passengers_ = new RWSet; passengers_->insert(s); } void Bus::addCustomer(const char* name) { customers_.insert( new Client(name) ); } /////////////// Here are Client methods ////////////// RWDEFINE_NAMED_COLLECTABLE(Client,"client") Client::Client() {} // Uses RWCString default constructor Client::Client(const char* name) : name_(name) {} RWspace Client::binaryStoreSize() const { return name_->binaryStoreSize(); } int Client::compareTo(const RWCollectable* c) const { return name_.compareTo(((Client*)c)->name_); } RWBoolean Client::isEqual(const RWCollectable* c) const { return name_ == *(Client*)c; } unsigned Client::hash() const { return name_.hash(); } void Client::restoreGuts(RWFile& f) { f >> name_; } void Client::restoreGuts(RWvistream& vis) { vis >> name_; } void Client::saveGuts(RWFile& f) const { f << name_; } void Client::saveGuts(RWvostream& vos) const { vos << name_; } main() { Bus theBus(1, "Kesey"); theBus.addPassenger("Frank"); theBus.addPassenger("Paula"); theBus.addCustomer("Dan"); theBus.addCustomer("Chris"); { // block controls lifetime of stream ofstream f("bus.str"); RWpostream stream(f); stream << theBus; // Persist theBus to an ASCII stream } { ifstream f("bus.str"); RWpistream stream(f); Bus* newBus; stream >> newBus; // Restore it from an ASCII stream cout << "Bus number " << newBus->number() << " has been restored; its driver is " << newBus->driver() << ".\n"; cout << "It has " << newBus->customers() << " customers and " << newBus->passengers() << " passengers.\n\n"; delete newBus; } return 0; }
Program Output:
Bus number 1 has been restored; its driver is Kesey. It has 4 customers and 2 passengers.