Я хочу сделать эквивалент следующего для инициализации члена данных 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
.
Я прав? Если да, что мне делать?
Ты сказал,
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
, как опубликовано, не является абстрактным базовым классом. Он не имеет никаких чистых виртуальных функций.
ABC
очевидно, не имеет каких-либо скрытых дополнительных чисто виртуальных функций-членов и, таким образом, фактически не является абстрактным ...
ABC*
вместо ABC&
, используйте какую-то функцию «клонирования» вместо конструктора копирования и уничтожьте my_abc
в ~SomeClass()
.
ABC
действительно абстрактен, вы не можете иметь экземпляр членаABC my_abc;
, Что вы можете сделать, это использовать ссылку:ABC& my_abc;
, Если не ваша копия выродится в простойABC
, это называется сплайсинг .