Есть ли в С++ механизм для создания полной копии производного класса из указателя базового класса без динамического выделения памяти?

Рассмотрим следующий пример, в котором нарезка объекта происходит во время разыменования базового указателя.

#include <stdio.h>

class Base {
  public:
    virtual void hello() {
        printf("hello world from base\n");
    }
};
class Derived : public Base{
  public:
    virtual void hello() {
        printf("hello world from derived\n");
    }
};

int main(){
    Base * ptrToDerived = new Derived;
    auto d = *ptrToDerived;
    d.hello();
}

Я хочу, чтобы переменная d содержала объект типа Derived вместо объекта типа Base, без динамического выделения памяти и без явного приведения.

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

Возможно ли это в C++11?


person merlin2011    schedule 17.05.2016    source источник
comment
Можете ли вы каким-то образом ограничить иерархию классов? Если количество типов ограничено, вы можете использовать boost::variant. Если бы вы могли ограничить максимально возможный размер объекта разумным значением, вы могли бы создать класс, похожий на умный указатель, для управления им.   -  person milleniumbug    schedule 18.05.2016
comment
@milleniumbug, на практике производный класс представляет собой шаблонный класс, поэтому я не думаю, что смогу его связать.   -  person merlin2011    schedule 18.05.2016


Ответы (2)


Нет, это невозможно, потому что если d не имеет динамической продолжительности хранения, то она должна иметь статическую, потоковую или автоматическую продолжительность хранения, и во всех этих случаях тип объекта известен во время компиляции. В вашем случае вы хотите, чтобы тип объекта определялся во время выполнения, поскольку ptrToDerived может указывать на объект Base или объект Derived или на объект какого-либо другого класса, производного от Base.

Если вас беспокоит время жизни и утечка памяти, просто пусть clone возвращает std::unique_ptr<Base> вместо Base*.

person Brian Bi    schedule 17.05.2016
comment
Это неудачно. Я избегаю динамического выделения памяти из соображений производительности. - person merlin2011; 18.05.2016
comment
@merlin2011: Посмотрите на вариант (например, boost::variant), который может хранить один из многих ваших производных классов в блоке памяти. Это заставляет вас, конечно, статически знать, какие производные классы вам могут понадобиться. - person GManNickG; 18.05.2016

Я думаю, вы имеете в виду, что хотите, чтобы auto вывел D.

Однако это невозможно: все типы должны быть известны во время компиляции. Представьте, если бы код был:

Base *b = some_func();
auto d = *b;

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

person M.M    schedule 17.05.2016