2

I have problem, I want to create unique pointer to vector of Base objects. I want keep in this vector subclass of Base (SubClass), but i have problem with initialization, because Base class is virtual.

std::unique_ptr<std::vector<Base>> baseVector = std::make_unique<std::vector<Base>>();
SubClass newObject();
baseVector->push_back(newObject);
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 3
    You don't need a pointer to the vector, but a pointer to the *base class*. Please try to [find a good beginners book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) as it will all be explained there. – Some programmer dude Jun 08 '17 at 11:41
  • You should use pointer to Base for storing the objects. See this https://stackoverflow.com/questions/2394581/pure-virtual-class-and-collections-vector – 0x0001 Jun 08 '17 at 11:41
  • 5
    You probably want `std::vector>` instead (or `std::vector` if vector doesn't have ownership). – Jarod42 Jun 08 '17 at 11:41
  • 1
    You'll need a vector of pointers to your base class. Also, _why_ do you need a pointer to a vector? What does it give you that aplain vector instance does not? – Rook Jun 08 '17 at 11:42
  • 2
    `SubClass newObject();` is a function declaration BTW. – Jarod42 Jun 08 '17 at 11:42

2 Answers2

6

Short Version: You don't want a dynamic pointer to a collection of Base; you want a collection of dynamic pointer-to-Base.

You seem to be misunderstanding where to place std::unique_ptr in your polymorphic collection. It isn't the collection that needs to be pointers for polymorphism to work; it's the object held within.

For example:

#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();
}

Output

DerivedOne
DerivedTwo
DerivedOne
DerivedTwo
DerivedOne
DerivedTwo

Whether you want the collection itself to be managed dynamically via a smart pointer is unrelated (and somewhat questionable) to this issue.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
2

A vector of Base doesn't support polymorphism. For this you need references or pointers or even better smart pointers:

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

add elements via

baseVector.push_back(std::make_unique<SubClass>());
mattideluxe
  • 468
  • 2
  • 12