Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

Can you make a vector of an abstract class?

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; Show activity on this post.

Can we declare object of abstract class in C ++?

You can't create an object of an abstract class type. However, you can use pointers and references to abstract class types. You create an abstract class by declaring at least one pure virtual member function. That's a virtual function declared by using the pure specifier ( = 0 ) syntax.

Can you have a vector of references C++?

It's a flaw in the C++ language. You can't take the address of a reference, since attempting to do so would result in the address of the object being referred to, and thus you can never get a pointer to a reference.

Can you declare a pointer to an object of an abstract class?

Abstract classes cannot be instantiated. However, you can declare a reference/pointer to an object that implements an abstract class, yes.


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.


You can't create a vector of an abstract class type because you cannot create instances of an abstract class, and C++ Standard Library containers like std::vector store values (i.e. instances). If you want to do this, you will have to create a vector of pointers to the abstract class type.

Your workround would not work because virtual functions (which is why you want the abstract class in the first place) only work when called through pointers or references. You cannot create vectors of references either, so this is a second reason why you must use a vector of pointers.

You should realise that C++ and C# have very little in common. If you are intending to learn C++, you should think of it as starting from scratch, and read a good dedicated C++ tutorial such as Accelerated C++ by Koenig and Moo.


In this case we can't use even this code:

std::vector <IFunnyInterface*> funnyItems;

or

std::vector <std::tr1::shared_ptr<IFunnyInterface> > funnyItems;

Because there is no IS A relationship between FunnyImpl and IFunnyInterface and there is no implicit convertion between FUnnyImpl and IFunnyInterface because of private inheritance.

You should update your code as follows:

class IFunnyInterface
{
public:
    virtual void IamFunny()  = 0;
};

class FunnyImpl: public IFunnyInterface
{
public:
    virtual void IamFunny()
    {
        cout << "<INSERT JOKE HERE>";
    }
};

The traditional alternative is to use a vector of pointers, like already noted.

For those who appreciate, Boost comes with a very interesting library: Pointer Containers which is perfectly suited for the task and frees you from the various problems implied by pointers:

  • lifetime management
  • double dereferencing of iterators

Note that this is significantly better than a vector of smart pointers, both in terms of performance and interface.

Now, there is a 3rd alternative, which is to change your hierarchy. For better insulation of the user, I have seen a number of times the following pattern used:

class IClass;

class MyClass
{
public:
  typedef enum { Var1, Var2 } Type;

  explicit MyClass(Type type);

  int foo();
  int bar();

private:
  IClass* m_impl;
};

struct IClass
{
  virtual ~IClass();

  virtual int foo();
  virtual int bar();
};

class MyClass1: public IClass { .. };
class MyClass2: public IClass { .. };

This is quite straightforward, and a variation of the Pimpl idiom enriched by a Strategy pattern.

It works, of course, only in the case where you do not wish to manipulate the "true" objects directly, and involves deep-copy. So it may not be what you wish.


Because to resize a vector you need to use the default constructor and the size of the class, which in turn requires it to be concrete.

You can use a pointer as other suggested.


std::vector will try to allocate memory to contain your type. If your class is purely virtual, the vector cannot know the size of the class it will have to allocate.

I think that with your workaround, you will be able to compile a vector<IFunnyInterface> but you won't be able to manipulate FunnyImpl inside of it. For example if IFunnyInterface (abstract class) is of size 20 (i dont really know) and FunnyImpl is of size 30 because it has more members and code, you will end up trying to fit 30 into your vector of 20

The solution would be to allocate memory on the heap with "new" and store pointers in vector<IFunnyInterface*>