Scott Nimrod
Scott Nimrod

Reputation: 11595

Cannot instantiate abstract class using c++11

Why can't I use an abstract class like an interface at runtime.

I get the output:

1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(615): error C2259: 'Creature' : cannot instantiate abstract class
1>          due to following members:
1>          'std::string Creature::Move(std::vector<std::string,std::allocator<_Ty>> &)' : is abstract
1>          with
1>          [
1>              _Ty=std::string
1>          ]

1>          visual studio 2013\projects\cpp_demo\cpp_demo\creature.h(9) : see declaration of 'Creature::Move'
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(614) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1>          with
1>          [
1>              _Ty=Creature
1>          ]

1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(752) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1>          with
1>          [
1>              _Ty=Creature
1>          ]

1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(580) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=Creature
1>          ]

1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<Creature>
1>          ]

1>          visual studio 2013\projects\cpp_demo\cpp_demo\main.cpp(7) : see reference to class template instantiation 'std::vector<Creature,std::allocator<_Ty>>' being compiled
1>          with
1>          [
1>              _Ty=Creature
1>          ]

My code:

int main()
{
    unique_ptr<vector<Creature>> pCreatures(new vector<Creature>);

    unique_ptr<Creature> pHuman(new Human());
    pCreatures->push_back(*pHuman);
}



#include "stdafx.h"
#include "Creature.h"

class Human : public Creature
{
public:
    virtual string Move(vector<string> &log);
};



#include "stdafx.h"
#include "IMove.h"

class Creature : public IMove
{
public:
    virtual string Move(vector<string> &log) = 0;
    virtual string GetState(vector<string> &log);
};

Please help.

Upvotes: 3

Views: 7262

Answers (2)

Amadeus
Amadeus

Reputation: 10655

You can use, but instead of using:

unique_ptr<vector<Creature>> pCreatures(new vector<Creature>);

use

vector<unique_ptr<Creature>> pCreatures;

so you will have a vectors of Creatures pointers, managed by unique_ptr.

There are, at least, two ways to use this vector:

  1. Creating the objects directly into the vector:

    pCreatures.emplace_back(new Human());

  2. Moving an unique_ptr to it:

    unique_ptr pHuman(new Human());

    pCreatures.push_back(move(pHuman));

Below is a compact usage:

int main()
{
  vector<unique_ptr<Creature>> pCreatures;

  pCreatures.emplace_back(new Human());

  unique_ptr<Creature> pHuman(new Human());
  pCreatures.push_back(move(pHuman));

  // example of usage
  pCreatures[0]->Move();
}

Upvotes: 1

Kan Li
Kan Li

Reputation: 8797

You CAN use abstract class in vector or unique_ptr, e.g.

#include <vector>
#include <memory>

using namespace std;

class Interface {
 public:
  virtual ~Interface() = 0;
};

Interface::~Interface() {}

class Implementation : public Interface {
};

int main(int argc, char** argv) {
  unique_ptr<Interface> p(new Implementation);
  vector<unique_ptr<Interface>> v;
  v.emplace_back(new Implementation);
  vector<Interface> vi;
  // This leads to compile error: vi.emplace_back();
}

Moreover, you CAN use vector<Interface> as long as you don't call any methods that potentially calls new Interface. For example, if you just declare a variable vector<Interface> v; it compiles, but if you push_back or emplace_back or resize, then it will have compile error because they will call new Interface.

The above code is tested under gcc-4.6.3.

Upvotes: 7

Related Questions