-1

So I'm new to C++, and my problem is this one: I have an abstract class, which as multiple child classes (and they had other child classes too). I am trying to use polymorphism to serialize and deserialize these child classes, and have, in my abstract class:

    virtual QDataStream& serialize(QDataStream& stream)=0;
    virtual QDataStream& deserialize(QDataStream &stream)=0;

So my question is simple: when I deserialize, I want to call the deserialize function, and I do not know yet which child class I am retrieving.

The function goes like this:

QDataStream& operator>>(QDataStream& in, SomeClass& i){

    std::shared_ptr<AbstractClass> ptr;
    ptr->deserialize(in); //Raises an SIGSEGV error

}

I don't know if I'm entirely clear, but basically what I'm trying to do is to instantiate and call whichever child class the stream corresponds to, and call deserialize on it. Is it possible ?

Thanks!

Edit: My first approach which works was to also feed the QDataStream my child class name, so that I know which class to instantiate:

        QString myClassName;
        in >> myClassName;
        if(myClassName == "ChildClass1"){
            std::unique_ptr<AbstractClass> ptr(new ChildClass1);
            ptr->deserialize(in);
        }

But I feel this is really not a clean OOP way!

trablazar
  • 25
  • 4

2 Answers2

0
 std::shared_ptr<AbstractClass> ptr;

A default initialised shared pointer points to null.

The behaviour of indirecting through a null pointer is undefined.

ptr->deserialize(in); //Raises an SIGSEGV error

This indirects through a null pointer. The behaviour of the program is undefined.


You can simplify your working example by getting rid of the dynamic allocation:

ChildClass1 c;
c.deserialize(in);

You don't need polymorphism in this case.


what I'm trying to do is to instantiate and call whichever child class [determined at runtime]

What you're attempting to implement here is essentially the factory method pattern. There is no simple way in a statically typed, non-reflective language such as C++ to implement factory method in a generic way. Most examples you'll find use a trivial if-else structure such as the one suggested by yourself.

You can see a few attempts at creating a generic factory method on another post, this answer appears appropriate in particular: https://stackoverflow.com/a/17408318/2079303. But as I said; not simple.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Hi @eerorika, thanks for the reply. I see the problem indeed, do you have a way to instantiate dynamically the child class ? Or is my first approach the only way ? – trablazar Jun 10 '19 at 18:09
  • Thanks for the clarification, really helped me! I was indeed looking toward templates, but I don't think I have yet reached the maturity to start using these. I will then go with a simple factory method, thanks ! – trablazar Jun 10 '19 at 18:27
  • @trablazar take care with reusing code from the linked answers though. Both the accepted answer, as well as the one I linked directly violate the standard by defining reserved identifiers. – eerorika Jun 10 '19 at 18:29
  • not to worry, I implemented my own, simple version of factory method, I don't think my project requires a generic factory method, a simple switch with identifiers will suffice! But many thanks for the warning, and for taking the time to answer! – trablazar Jun 10 '19 at 18:45
0

It is unfortunately not possible to initialize a child class from the base class only. When serialising you will have to serialise some sort of id for the child class. Next when deserializing I suggest you use the factory pattern. Using a factory you pass the id and class data you wish to deserialize. That factory function will construct the required child class and return a pointer to the base class.

Bart
  • 1,405
  • 6
  • 32