所以我是C++新手,我的问题是这个: 我有一个抽象类,它作为多个子类(它们还有其他子类)。我正在尝试使用多态性来序列化和反序列化这些子类,并且在我的抽象类中具有:
virtual QDataStream& serialize(QDataStream& stream)=0;
virtual QDataStream& deserialize(QDataStream &stream)=0;
所以我的问题很简单:当我反序列化时,我想调用反序列化函数,但我还不知道我正在检索哪个子类。
函数如下所示:
QDataStream& operator>>(QDataStream& in, SomeClass& i){
std::shared_ptr<AbstractClass> ptr;
ptr->deserialize(in); //Raises an SIGSEGV error
}
我不知道我是否完全清楚,但基本上我要做的是实例化并调用流对应的任何子类,并对其调用反序列化。可能吗?
谢谢!
编辑:我的第一个有效的方法是也向QDataStream提供我的子类名称,以便我知道要实例化哪个类:
QString myClassName;
in >> myClassName;
if(myClassName == "ChildClass1"){
std::unique_ptr<AbstractClass> ptr(new ChildClass1);
ptr->deserialize(in);
}
但我觉得这真的不是一个干净的OOP方式!
遗憾的是,无法仅从基类初始化子类。序列化时,您必须序列化子类的某种 id。接下来,在反序列化时,我建议您使用工厂模式。使用工厂传递要反序列化的 id 和类数据。该工厂函数将构造所需的子类并返回指向基类的指针。
std::shared_ptr<AbstractClass> ptr;
默认初始化的共享指针指向 null。
通过空指针进行间接的行为是不确定的。
ptr->deserialize(in); //Raises an SIGSEGV error
这通过空指针间接进行。程序的行为是未定义的。
您可以通过摆脱动态分配来简化您的工作示例:
ChildClass1 c;
c.deserialize(in);
在这种情况下,您不需要多态性。
我试图做的是实例化并调用任何子类[在运行时确定]
您在此处尝试实现的实质上是工厂方法模式。在静态类型、非反射语言(如 C++)中,没有简单的方法以通用方式实现工厂方法。你会发现的大多数例子都使用一个微不足道的if-else结构,比如你自己建议的结构。
您可以在另一篇文章中看到一些创建通用工厂方法的尝试,这个答案似乎特别合适:https://stackoverflow.com/a/17408318/2079303。但正如我所说;不简单。