Скопируйте объект, полученный из абстрактного класса - PullRequest
0 голосов
/ 05 мая 2018

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

В моем классе схема у меня есть гетерогенный std::vector<sim::component*> с именем component_list, который я использую для обработки всех компонентов, вставленных в схему.

Тогда у меня есть следующая функция:

void circuit::insert(sim::component& comp, std::vector<sim::node*> nodes)

В определении функции я хочу скопировать компонент с именем comp чтобы вставить указатель на него в моем component_list (чтобы я мог управлять его временем жизни)

Я пробовал что-то в этом роде:

sim::component *copy = new sim::component(comp)

но, конечно, sim :: component является абстрактным, и я не могу его создать

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

1 Ответ

0 голосов
/ 05 мая 2018

Один из традиционных способов решения этой проблемы - позволить объектам клонировать себя, плюс немного CRTP.

I. Сначала вы делаете свой абстрактный класс клонируемым:

struct Component {
    virtual Component *clone() const = 0;
    virtual ~Component() {}
};

Теперь каждый Компонент должен определить свою собственную реализацию clone().

II. Который легко автоматизируется через CRTP:

template<class Concrete> struct CompBase: Component {
    Component *clone() const {
        return new Concrete(static_cast<Concrete const &>(*this));
    }
    virtual ~CompBase() {}
};

struct Generator: CompBase<Generator>;  // already has clone() defined

Обратите внимание, что в примере я использовал простые указатели, хотя обычно рекомендуется использовать более умные аналоги. std::unique_ptr вполне подойдет, вместе с std::make_unique.

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

...