Уникальный указатель на вектор и полиморфизм

У меня проблема, я хочу создать уникальный указатель на вектор базовых объектов. Я хочу сохранить в этом векторном подклассе Base (SubClass), но у меня проблема с инициализацией, потому что базовый класс виртуальный.

std::unique_ptr<std::vector<Base>> baseVector = std::make_unique<std::vector<Base>>();
SubClass newObject();
baseVector->push_back(newObject);

person Radosław Gadowski    schedule 08.06.2017    source источник
comment
Вам нужен не указатель на вектор, а указатель на базовый класс. Пожалуйста, попробуйте найти хорошую книгу для начинающих, поскольку все это будет объяснено там.   -  person Some programmer dude    schedule 08.06.2017
comment
Вы должны использовать указатель на Base для хранения объектов. См. Этот stackoverflow.com/questions/2394581/   -  person 0x0001    schedule 08.06.2017
comment
Вы, вероятно, захотите вместо этого std::vector<std::unique_ptr<Base>> (или std::vector<Base*>, если у вектора нет владельца).   -  person Jarod42    schedule 08.06.2017
comment
Вам понадобится вектор указателей на ваш базовый класс. Кроме того, зачем вам нужен указатель на вектор? Что это дает вам, чего нет в экземпляре простого вектора?   -  person Rook    schedule 08.06.2017
comment
SubClass newObject(); - это объявление функции, кстати.   -  person Jarod42    schedule 08.06.2017


Ответы (2)


Краткая версия: вам не нужен динамический указатель на коллекцию Base; вам нужна коллекция динамических указателей на Base.

Похоже, вы не понимаете, где разместить std::unique_ptr в вашей полиморфной коллекции. Указателями для работы полиморфизма должна быть не коллекция; это объект, удерживаемый внутри.

Например:

#include <iostream>
#include <vector>
#include <memory>

struct Base
{
    virtual ~Base() {}

    virtual void foo() const = 0;
};

class DerivedOne : public Base
{
public:
    virtual void foo() const
    {
        std::cout << "DerivedOne\n";
    }
};

class DerivedTwo : public Base
{
public:
    virtual void foo() const
    {
        std::cout << "DerivedTwo\n";
    }
};

int main()
{
    std::vector< std::unique_ptr<Base> > objs;

    objs.emplace_back(std::make_unique<DerivedOne>());
    objs.emplace_back(std::make_unique<DerivedTwo>());

    // via operator[]
    objs[0]->foo();
    objs[1]->foo();

    // via range-for
    for (auto const& p : objs)
        p->foo();

    // via iterators
    for (auto it = objs.begin(); it !=objs.end(); ++it)
        (*it)->foo();
}

Вывод

DerivedOne
DerivedTwo
DerivedOne
DerivedTwo
DerivedOne
DerivedTwo

Если вы хотите, чтобы сама коллекция управлялась динамически с помощью интеллектуального указателя, это не связано (и несколько сомнительно) с этой проблемой.

person WhozCraig    schedule 08.06.2017
comment
Спасибо за решение :) - person Radosław Gadowski; 08.06.2017
comment
Да, у меня это сработало, и я сделал из этого сложный пример, так как мои потребности немного отличаются от этого. Но работает, спасибо. - person CharlesW; 16.06.2021

Вектор Base не поддерживает полиморфизм. Для этого вам понадобятся ссылки или указатели или даже лучше умные указатели:

auto baseVector = std::make_unique<std::vector<Base*>>();
auto baseVector = std::make_unique<std::vector<std::unique_ptr<Base>>>();

добавить элементы через

baseVector.push_back(std::make_unique<SubClass>());
person mattideluxe    schedule 08.06.2017