所以我有这些课程。有一个基类,但它有/将有很多很多的派生类,这些派生类也可以有派生类。我希望能够拥有一个将其二进制数据写入文件的函数,但我不确定如何使用大量派生类来做到这一点。
我在想一些事情:
void writeData(ofstream & _fstream)
{
_fstream.write()//etc..
}
但是实现这个方法的每个派生类都必须写它所有的父类的数据,这会重复很多代码。
在不重写所有以前编写的writeData()代码的情况下,最好的方法是什么?
所以我有这些课程。有一个基类,但它有/将有很多很多的派生类,这些派生类也可以有派生类。我希望能够拥有一个将其二进制数据写入文件的函数,但我不确定如何使用大量派生类来做到这一点。
我在想一些事情:
void writeData(ofstream & _fstream)
{
_fstream.write()//etc..
}
但是实现这个方法的每个派生类都必须写它所有的父类的数据,这会重复很多代码。
在不重写所有以前编写的writeData()代码的情况下,最好的方法是什么?
您可以从派生类实现中调用基类实现:
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..
}
派生类可以调用基write方法来避免代码重复。事实上,如果某些父母的数据是私有的但仍被间接使用,这可能是唯一的方法。
如果你想避免重新设计所有派生类的序列化函数实现,你可以从另一个方向走,从基类到派生类:
在您的基类中提供一个非virtual函数来启动序列化过程。客户端代码通过指针(或引用)调用此函数。还提供一个为子类进行序列化的虚函数。从基类的函数中调用该Serialize函数。
(编辑)如果您想为序列化子类提供默认功能,但仍希望能够为特定情况提供专门的功能,那么序列化子类的函数不必是纯虚拟的。但是,通过阅读您的 OP,在我看来,每个子类都需要提供此功能。为了模拟该要求,我在DoSerialize这里将函数设为纯虚拟。
例子:
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();
}
最终,每个派生类都有责任确保它已被正确序列化。派生类可能需要在基类之前或之后序列化一些数据,具体取决于其用途。它可能还想完全覆盖基类数据的序列化方式。
这么看——这里执行的功能是序列化和反序列化。这里的关键是它需要正确执行。因此,唯一能够做到这一点的班级是拥有完整知识的班级。换句话说,它是您的派生类。
因此,有时您必须调用 Base::writeData(),但是否这样做应该完全由派生类决定。请记住,您想要的是让您的类层次结构满足一些基本设计原则。一旦你有了它,它应该相对容易。