Why Can't We Declare a Std::Vector≪Abstractclass≫

Why can't we declare a std::vector<AbstractClass>?

You can't instantiate abstract classes, thus a vector of abstract classes can't work.

You can however use a vector of pointers to abstract classes:

std::vector<IFunnyInterface*> ifVec;

This also allows you to actually use polymorphic behaviour - even if the class wasn't abstract, storing by value would lead to the problem of object slicing.

Why I can not use abstract class in std::vector?

As far as I know, Data are dynamically allocated in std::vector which means that there is pointers internally in the std::vector

That's absolutely right. However, the pointer (actually, one of two pointers in the very common implementation) points to an array of identically-sized elements of type T, not to a single element of T or its subtype. Essentially, the pointer is used to represent an array, not to refer to a class or its subclass.

That is why you need an extra level of indirection - elements of an array T[] are not capable of storing subclasses of T without object slicing.

How to declare a vector list of abstract class in C++?

Problem is with creatures.push_back(Bird("duck", true));
You are creating a Bird object and copying that in the Animal object.
One way is to create objects dynamically so that correct function call can resolve using vtable.
Modify this part of your code and it will work fine.

vector<Animal *> creatures;

creatures.push_back(new Bird("duck", true));
creatures.push_back(new Bird("penguin", false));
creatures.push_back(new Insect("spider", 8));
creatures.push_back(new Insect("centipede",44));

Edit: Make sure to release the memory before creatures goes out of scope.

abstract classes in std containers

One solution if you compiler supports C++11 features, would be to use std::vector<std::shared_ptr<foo>> or std::vector<std::unique_ptr<foo>>instead of raw pointers like the example below:

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

struct foo {
virtual void print() = 0;
};

struct goo : public foo {
int a;
void print() { std::cout << "goo"; }
};

struct moo : public foo {
int a,b;
void print() { std::cout << "moo"; }
};

auto main() -> int {
std::vector<std::shared_ptr<foo>> v{std::make_shared<goo>(), std::make_shared<moo>()};
for(auto i : v) {
i->print();
std::cout << std::endl;
}
return 0;
}

or with std::vector<std::unique_ptr<foo>>:

auto main() -> int {
std::vector<std::unique_ptr<foo>> v;
v.push_back(std::move(std::unique_ptr<goo>(new goo)));
v.push_back(std::move(std::unique_ptr<moo>(new moo)));
for(auto it(v.begin()), ite(v.end()); it != ite; ++it) {
(*it)->print();
std::cout << std::endl;
}
return 0;
}

Thus, you wouldn't have to worry about memory deallocation.



Related Topics



Leave a reply



Submit