You failed to define
Serialize() in
SeekableSerializer.
Serializer::Serialize() is a pure virtual function and any classes that derive from it
must define it. E.g., your code should look like this:
class Serializer {
public:
virtual void Serialize(char* buffer, size_t size) = 0;
};
class SeekableSerializer : public Serializer {
public:
/**
* Pure virtual function, this class cannot be
* instantiated on its own because it's abstract.
*/
virtual void SeekRelative(int offset) = 0;
/**
* Makes this function unambiguous though the above function
* is pure virtual so this is still an abstract class.
*/
virtual void Serialize(char* buffer, size_t size) final
{}
};
As noted above, though,
SeekableSerializer is still an abstract class because the function
SeekRelative is pure virtual. Though this may be moot as you do define it in
FileStreamReader (I think?).
Additionally,
SeekableStreamReader and
FileStreamReader do not declare virtual destructors. If you're inheriting, your destructors must be virtual in order to be called correctly when a derived object is destroyed.
Finally,
StreamReader's destructor is pure virtual. While this is legal C++, you still need to define it. You can do this in the
.cpp file simply as this:
StreamReader::~StreamReader() {}
Doesn't need to be any more fancy than that.
Side note about inheriting virtual functions -- even in the derived class you should declare it virtual. This is more of a documentation type of deal than anything else but if you don't want the implementation to be overridden in a further derived class you can define the function final:
class FileStreamReader : public SeekableStreamReader {
public:
FileStreamReader(std::string fileName);
virtual ~FileStreamReader();
virtual void Serialize(char* buffer, size_t size) final;
/** Change position forward or backword in buffer. */
virtual void SeekRelative(int offset) final;
private:
std::ifstream file;
};
Perhaps inheritance isn't the best option. Perhaps class composition would work better. After all, inheritance is not the best option in every case involving classes.
No, in this case inheritance is the correct approach (and actually in this case multiple inheritance makes sense). The intent here is to inherit an interface, not an implementation.
The parent classes provide interface functions but no implementations. Implementations are provided by the derived classes by defining pure virtual functions.