-Поиск по дневнику

Поиск сообщений в rss_forum_sources_ru

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 29.07.2007
Записей:
Комментариев:
Написано: 80


двухшаговая инициализация

Воскресенье, 02 Августа 2020 г. 12:42 + в цитатник
Twilight: Добрый день.
Постоянно сталкиваюсь со следующей проблемой: есть фабричный метод для создания объектов, в зависимости от некоторых условий, также есть некий набор входных данных, который нужно передать во вновь созданный объект.
Ниже псевдокод, описывающий текущее решение
    class IObject
    {
    public:
    virtual ~IObject() {}
    virtual void initialize( const ObjectData &objectData ) = 0;
    };
    class AbstractObject : public IObject
    {
    public:
    virtual void initialize( const ObjectData& objectData ) override
    {
    m_objectData = &objectData;
    }
    private:
    ObjectData *m_objectData;
    };
    class ObjectA : public AbstractObject {};
    class ObjectB : public AbstractObject {};
    IObject* create( int type )
    {
    if( type == 1 ) return new ObjectA;
    return newObjectB;
    }


соответственно используется примерно так:
    IObject *obj = create( type );
    obj->initialize( objectData );

в целом, данный подход устраивает, если бы не одно НО: так как ObjectData передается не в конструктор, то внутри AbstractObject мне приходится держать не константную ссылку, как хотелось бы, а простой указатель. С одной стороны я знаю, что данный указатель получен из ссылки, и, таким образом, не может быть nullptr. Однако при разрастании кода, об этом можно забыть и все-таки влепить проверки из серии if( m_objectData ).

Альтернативный подход, который я вижу - это передача ObjectData в конструкторе:
    class IObject
    {
    public:
    virtual ~IObject() {}
    };
    class AbstractObject : public IObject
    {
    public:
    AbstractObject( const ObjectData &objectData ) {}
    };
    class ObjectA : public AbstractObject
    {
    public:
    ObjectA( const ObjectData &objectData ) : AbstractObject( objectData ) {}
    };
    class ObjectB : public AbstractObject
    {
    public:
    ObjectB( const ObjectData &objectData ) : AbstractObject( objectData ) {}
    };
    IObject* create( int type, const ObjectData &objectData )
    {
    if( type == 1 ) return new ObjectA( objectData );
    return new ObjectB( objectData );
    }


Такой вариант меня не устраивает прежде всего тем, что в каждом наследуемом классе необходимо писать один и тот же код, для передачи ObjectData в базовый класс.

Т.е. получается, что для решения проблемы варианта 1 ( хранение указателя, вместо ссылки ) отлично подходит варинт 2, но с другой стороны он привносит необходимость прокидывания ObjectData через всю иерархию наследования, чего как раз нет в варианте 1.

Возможен ли "третий" вариант, в котором нет вышеперечисленных минусов?

https://forum.sources.ru/index.php?showtopic=419313&view=findpost&p=3835721

Метки:  

 

Добавить комментарий:
Текст комментария: смайлики

Проверка орфографии: (найти ошибки)

Прикрепить картинку:

 Переводить URL в ссылку
 Подписаться на комментарии
 Подписать картинку