Как инициализировать при создании абстрактный член данных базового класса из экземпляра производного класса

0

Я хочу сделать эквивалент следующего для инициализации члена данных my_abc (который, как я подозреваю, не будет работать):

class ABC { // abstract base class
public:
    virtual ~ABC {};
}

class SomeClass {
public:
    SomeClass(ABC& abc); // argument will actually be instance of derived class
private:
    ABC my_abc; // needs to be set from constructor argument
}

SomeClass::SomeClass(ABC& abc) : my_abc(abc)
{...} // copy construct 'my_abc' from argument

Я подозреваю, что это не сработает, когда производный класс ABC передается конструктору SomeClass потому что конструктор копирования производного класса не будет вызываться для инициализации члена my_abc.

Я прав? Если да, что мне делать?

  • 5
    Если ABC действительно абстрактен, вы не можете иметь экземпляр члена ABC my_abc; , Что вы можете сделать, это использовать ссылку: ABC& my_abc; , Если не ваша копия выродится в простой ABC , это называется сплайсинг .
  • 0
    @ πάνταῥεῖ уверен, что вы имели в виду нарезку (чтобы разделить), а не сплайсинг (чтобы собрать). = Р
Показать ещё 1 комментарий
Теги:

1 ответ

4
Лучший ответ

Ты сказал,

SomeClass(ABC& abc);//argument will actually be instance of derived class

и тогда у вас есть данные участника

ABC my_abc;

Если вы инициализируете my_abc с помощью abc, вы получите объект базового класса, который не будет захватывать часть производного класса. Оформить вопрос о разрезе объектов. Это то, чего вы надеетесь достичь? Думаю, нет.

Как упоминалось в комментарии от πάντα ῥεῖ, вы должны сохранить ссылку на базовый класс.

ABC& my_abc_ref;

Затем,

SomeClass::SomeClass(ABC& abc) : my_abc_ref(abc) {...}

не должно быть проблемой.

Если вы хотите иметь копию входного объекта, вам нужно клонировать входной объект и поддерживать время жизни клонированного объекта. Вы можете использовать интеллектуальный указатель для этого.

class ABC {
public:
    virtual ~ABC() {}
    virtual ABC* clone() const = 0;
};

#include <memory>

class SomeClass {
public:
    SomeClass(ABC& abc);
private:
    std::unique_ptr<ABC> my_abc;
};

SomeClass::SomeClass(ABC& abc) : my_abc(abc.clone()) {}

Это просто показывает механизм. Чтобы создать код качества продукции, вы должны принять политические решения о поведении копирующих и перемещающих конструкторов, а также скопировать и переместить операторы присваивания SomeClass и соответствующим образом реализовать их.

PS

Класс ABC, как опубликовано, не является абстрактным базовым классом. Он не имеет никаких чистых виртуальных функций.

  • 0
    Возможно, стоит упомянуть, что ABC очевидно, не имеет каких-либо скрытых дополнительных чисто виртуальных функций-членов и, таким образом, фактически не является абстрактным ...
  • 0
    Если это действительно абстрактно, возможно, используйте ABC* вместо ABC& , используйте какую-то функцию «клонирования» вместо конструктора копирования и уничтожьте my_abc в ~SomeClass() .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню