Как выделить память для объекта, которого я не знаю реального типа? C ++

StackOverflow https://stackoverflow.com/questions/4299298

Вопрос

Я хочу хранить объект какого-либо производного класса как свойство другого объекта.

Проблема для меня состоит в том, чтобы знать размер объекта, который нужно хранить, как это может быть любой полученный класс данного базового класса. Я не могу просто выделить память для объекта базового класса, верно, так как он меньше. Я полагаю, тип Оператор также просто даст размер базового класса, верно?

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

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 Чтобы выделить объект свойства на кучу (так как вы делаете копию внутри BaseBS конструктор в любом случае, по крайней мере, общее потребление памяти не поднимется, хотя)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top