lowq
lowq

Reputation: 628

Writing polymorphic class data to a file?

So I have these classes. There's one base class, but it has/will have lots and lots of derivatives, and those derivative classes will be able to have derivatives as well. I'd like to be able to have a function that writes their binary data to a file, but I'm not sure how to do this with lots and lots of derived classes.

I was thinking something along the lines of:

void writeData(ofstream & _fstream)
{
    _fstream.write()//etc..
}

But then each derived class that implemented this method would have to write all of it's parent class's data, and that would be duplicating a lot of code.

What's the best way to do this without rewriting all of the previously written writeData() code?

Upvotes: 4

Views: 1441

Answers (4)

Carl
Carl

Reputation: 44448

Ultimately, it is the responsibility of each derived class to make sure that it has been serialized properly. A derived class may need to serialize some data before or after the base class, depending on its purpose. It may also want to totally override the way the base class data is serialized.

Look at it this way - the function being performed here is serialization and de-serialization. The critical thing here is that it needs to be performed correctly. Therefore, the only class that is in a good position to do this is the one with complete knowledge. In other words, its your derived class.

So, there are times when you will have to call Base::writeData(), but whether or not you do that should be left totally up to the derived class. Remember, what you want is for your class hierarchy to satisfy some basic design principles. Once you've got that, it should be relatively easy.

Upvotes: 0

John Dibling
John Dibling

Reputation: 101456

If you want to avoid re-engineering all the derived class' implementation of the serialization functions, you can go in the other direction, from the base to the derived classes:

In your base class provide a non-virtual function to start the serialization process. Client code calls this function via a pointer (or reference). Also provide a virtual function that does the serialization for the subclass. Call that function from the base class' Serialize function.

(EDIT) If you want to provide default functionality for serializing the subclasses, but still want to be able to provide specialized functionality for specific cases, then the function that serializes the subclasses need not be pure virtual. However, by my reading of your OP it seemed to me that every subclass would need to be required to provide this functionality. To model that requirement, I have made the DoSerialize function pure virtual here.

Example:

class Base
{
public:
  void Serialize() const;
  virtual void DoSerialize() = 0;
};

class Derived : public Base
{
public:
  void DoSerialize() { /* MAGIC HAPPENS */ };
};

void Base::Serialize() const
{
  /* .. do serialization of base class here, or at the end -- whichever is appropriate .. */

  this->DoSerialize();  // serialize the derived class
}

/* ... */

Base* GetObject()
{
 /* ... */
}

int main()
{
  Base* obj = GetObject();
  obj->Serialize();
}

Upvotes: 1

user405725
user405725

Reputation:

Derived class can call base write methods to avoid code duplication. In fact, that may be the only way to go if some parent's data is private but still is indirectly used.

Upvotes: 4

filipe
filipe

Reputation: 3380

You can call the base class implementation from the derived class implementation:

void Derived::writeData(ofstream & _fstream)
{
    // Base class writes its data
    Base::writeData(_fstream);

    // now I can write the data that is specific to this Derived class
    _fstream.write()//etc..
}

Upvotes: 9

Related Questions