Как выделить память для объекта, которого я не знаю реального типа? C ++
-
29-09-2019 - |
Вопрос
Я хочу хранить объект какого-либо производного класса как свойство другого объекта.
Проблема для меня состоит в том, чтобы знать размер объекта, который нужно хранить, как это может быть любой полученный класс данного базового класса. Я не могу просто выделить память для объекта базового класса, верно, так как он меньше. Я полагаю, тип Оператор также просто даст размер базового класса, верно?
Вот мой пример кода. Пожалуйста, посмотрите комментарии, чтобы понять, что я имею в виду. Простите за неоригинальность ...
BaseA {};
DerivedA1 : BaseA {public: void property() { cout << 1; }};
DerivedA2 : BaseA {public: void property() { cout << 2; }};
// etc. - several derived classes.
BaseB // Contains (or links to) an instance of class derived from BaseA.
{
public:
BaseA * instanceA;
BaseB (BaseA instanceAX)
{
// ??? => How to allocate memory for the object
// I don't know the real type of?
instanceA = new BaseA (instanceAX);
}
BaseB (BaseA instanceAX) { delete instanceA; }
};
main()
{
DerivedA1 instanceA1;
BaseB instanceB (instanceA1);
// Use "property" regardless of which derived class it belongs to.
instanceB.instanceA->property();
}
Я мог хранить указатель вместо самого объекта, было бы проще. Но я не уверен, что хочу полагаться на абонента, чтобы сохранить объект недвижимости для жизни экземпляра экземпляр.
Спасибо!
Решение
Ну, прежде всего, так как вы проходите в базе по значению, а не со ссылкой или указателем, вы знаете тип; Это призыв. BASEB был скопирован в Basea и что копия Basea отправляется на функцию. Любые дополнительные данные в BASEB не содержатся в Instanceax. Это называется «нарезка».
Но, чтобы ответить на ваш вопрос, вы просто не делаете это так. Вам нужна функция клона () в вашем классе BaseB, если она должна работать таким образом. В качестве альтернативы вы можете разработать умный указатель или другой объект, который может клонировать экземпляр для вас. Если вы ищете мое имя на comp.lang.c ++ вместе с Clone (), вы можете встретить дискуссию, которую я провел об этой последней идее.
Функция клона, конечно, является виртуальной функцией, которая возвращает копию текущего объекта:
struct BaseA
{
virtual BaseA* clone() const = 0;
};
struct BaseB : BaseA
{
BaseB* clone() const { return new BaseB(*this); }
};
Другие советы
Я вижу две возможности.
Дайте
BaseA
Чисто виртуальная функция участника, возможно, вызываетсяclone
, это отвечает за создание копии экземпляра, на которой она называется. Тогда конструкторBaseB
может статьBaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }
Вы также можете просто избежать передачи необработанных указателей и использовать
boost::shared_ptr
вместо. Таким образом, поскольку он связан с ссылкой, ваш абонент не может вызвать преждевременное уничтожениеBaseA
вывод, который был использован для построенияBaseB
. Отказ Вам придется настроитьBaseA * instanceA;
читатьboost::shared_ptr <BaseA> instanceA;
ЗатемBaseB
Конструктор может выглядеть:BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }
Проблема первого поступления в том, что какой -то клиент -программист, который наследует, скажем, скажем, DerivedA1
может забыть реализовать clone
в его выводе. Основная проблема второго апреля будет требовать каждого пользователя BaseB
Чтобы выделить объект свойства на кучу (так как вы делаете копию внутри BaseB
S конструктор в любом случае, по крайней мере, общее потребление памяти не поднимется, хотя)