Как инициализировать дочерний класс из указателя на его абстрактный материнский класс? - PullRequest
0 голосов
/ 10 июня 2019

Итак, я новичок в 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);
        }

Но я чувствую, что это действительно не чистый ООП путь!

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

К сожалению, невозможно инициализировать дочерний класс только из базового класса.При сериализации вам придется сериализовать какой-то идентификатор для дочернего класса.Далее при десериализации я предлагаю вам использовать шаблон factory .Используя фабрику, вы передаете идентификатор и данные класса, которые хотите десериализовать.Эта фабричная функция создаст требуемый дочерний класс и вернет указатель на базовый класс.

0 голосов
/ 10 июня 2019
 std::shared_ptr<AbstractClass> ptr;

Инициализированный по умолчанию общий указатель указывает на ноль.

Поведение косвенных указателей через нулевой указатель не определено.

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

Это косвенное указание через нулевой указатель. Поведение программы не определено.


Вы можете упростить свой рабочий пример, избавившись от динамического выделения:

ChildClass1 c;
c.deserialize(in);

В этом случае вам не нужен полиморфизм.


я пытаюсь создать экземпляр и вызвать любой дочерний класс [определенный во время выполнения]

Здесь вы пытаетесь реализовать шаблон фабричного метода . В статически типизированном неотражающем языке, таком как C ++, нет простого способа реализовать фабричный метод универсальным способом. В большинстве примеров вы найдете тривиальную структуру if-else, такую ​​как предложенная вами.

Вы можете увидеть несколько попыток создания универсального фабричного метода в другом посте, этот ответ, в частности, кажется уместным: https://stackoverflow.com/a/17408318/2079303. Но, как я уже сказал; не просто.

...