10

If I have a base class and a derived class, I can create a vector of base class pointers, if I want to group multiple base and/or derived classes together in a container.

Example:

class base
{
}

class derived : public base
{
}

std::vector<base*> group;

But is it possible to do the following?

std::vector<base> group;

ie: Without the pointers, which require newing and deleteing?

Edit: In 2015 I didn't know about polymorphism, if you are reading this question in 2022 it would be worth searching for some information about that.

To give a bit of color on this, a std::vector is a template class which takes a template parameter T. You may think of it as

template<typename T>
std::vector<T>

All this means is that a std::vector contains elements of the same type. T describes the type. C++ is statically typed, meaning that all the types are specified at compile time.

T can be one of many different types. However, each instance of a std::vector contains elements of the same type.

This is in part because the compiler needs to know how large T is. In other words, what size does it occupy in memory? This is a fairly obvious constraint. You cannot pack elements into memory unless the size of the elements are known. Further, you cannot jump to an element within an array in O(1) time, unless the index of the element can be converted into a memory address using a multiplication.

When it comes to pointers, all pointers are the same size. Therefore you can create a std::vector<base*>. However, a class base may not have the same size as class derived, therefore you cannot create a std::vector<base or derived>.

As others have explained in the answers, a std::vector<base> will not behave polymorphically.

2
  • 3
    No it is not. Look up "object slicing". Commented Dec 20, 2015 at 17:54
  • @n.m. Instructive, thanks Commented Dec 20, 2015 at 17:57

2 Answers 2

19

Yes you can use vector<base> & the compiler won't raise any error for this usage. However, the problem with vector<base> is that it fails to achieve polymorphism. See below :-

#include <iostream>
#include <vector>
using namespace std;

class base
{
    int x, id;
    static int i;
    public:
    base()
    {
        id = ++i;
        cout << "Base constructed: " << id << "\n";
    }
    base (const base &b)
    {
        id = ++i;
        cout << "Base copy constructed: " << id << "\n";
    }
    virtual int& getx()
    {
        cout << "Base getx() called\n";
        return x;
    }
    virtual ~base()
    {
        cout << "Base destroyed: " << id << "\n";
    }
};
int base :: i = 0; 

class derived : public base
{
    int x, id;
    static int j;
    public:
    derived()
    {
        id = ++j;
        cout << "Derived constructed: " << id << "\n";
    }
    derived (const derived& d)
    {
        id = ++j;
        cout << "Derived copy constructed: " << id << "\n";
    }
    virtual int& getx()
    {
        cout << "Derived getx() called\n";
        return x;
    }
    virtual ~derived()
    {
        cout << "Derived destroyed: " << id << "\n";
    }
};
int derived :: j = 0;

int main()
{
    vector<base> v;
    v.emplace_back(derived());
    v[0].getx() = 7;
    cout << "\n\n";
    for (int i=0; i<v.size(); ++i)
    cout << v[i].getx() <<"\n";
    cout << "\n\n";
    return 0;
}
/* Output :-
Base constructed: 1
Derived constructed: 1
Base copy constructed: 2
Derived destroyed: 1
Base destroyed: 1
Base getx() called


Base getx() called
7


Base destroyed: 2
*/

You can clearly see that although the object is of derived neither the copy constructor of derived is called nor getx() of the same. So the purpose of using vector<base> to achieve polymorphism is defeated. Hence you should never use vector<base> & rather prefer vectors of smart pointers or raw pointers.

Sign up to request clarification or add additional context in comments.

Comments

14

You can't do vector<base>, but you can do vector<unique_ptr<base>> and avoid having to write new or delete manually. Use make_unique instead of new and delete gets handled for you automagically.

2 Comments

Make_unique is C++14 and does not allow you to specify a custom deleter, so it's not a direct replacement. YMMV
@James: It's supported by popular implementations at this time. And you don't need a custom deleter when the previous thing was a direct delete call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.