title: Undefined reference to vtable with nested class
body: <p>When I try to compile the following code:</p>
  
  <pre><code>Alien::Action::Action(ActionType type, float x, float y) {
      Action::type = type;
      pos = Vec2(x, y);
  }
  
  Alien::Alien(float x, float y, int nMinions) {
      srand(time(NULL));
      sp = Sprite("img/alien.png");
      box = Rect(x, y, sp.GetWidth(), sp.GetHeight());
      box.x = x - box.h/2;
      box.y = y - box.w/2;
      hitpoints = 100;
      speed.x = 0.5;
      speed.y = 0.5;
      minionArray = std::vector&lt;Minion&gt;();
      for(int i = 0; i &lt; nMinions; i++) {
          int a = rand()%501;
          float b = a/1000.0;
          float c = b+1;
          minionArray.emplace_back(Minion(get(), i*(360/nMinions), c));
      }
      taskQueue = std::queue&lt;Action&gt;();
  }
  </code></pre>
  
  <p>The IDE (Eclipse) gives the following error message: "undefined reference to 'vtable for Alien'" (line 6 of the code). Since there's no virtual method inside Alien, I don't know the cause of the error. The following is the header file for Alien:</p>
  
  <pre><code>#ifndef ALIEN_H_
  #define ALIEN_H_
  
  #include "GameObject.h"
  
  class Alien: public GameObject {
  private:
      class Action {
      public:
          enum ActionType {MOVE, SHOOT};
          ActionType type;
          Action(ActionType type, float x, float y);
          Vec2 pos;
      };
      int hitpoints;
      std::queue&lt;Action&gt; taskQueue;
      std::vector&lt;Minion&gt; minionArray;
  public:
      Alien(float x, float y, int nMinions);
      ~Alien();
      void Update(float dt);
      void Render();
      Alien* get();
      bool IsDead();
  };
  
  #endif
  </code></pre>
  
  <p>The code for GameObject is :</p>
  
  <pre><code>#include "GameObject.h"
  #include "InputManager.h"
  #include "Camera.h"
  #include "State.h"
  
      GameObject::~GameObject() {
  
      }
  
      GameObject* GameObject::get() {
          return this;
      }
  
      Minion::~Minion() {
  
      }
  
      Minion::Minion(GameObject* minionCenter, float arcOffset, float minionSize) {
          sp = Sprite("img/minion.png");
          center = minionCenter;
          translation = arcOffset;
          box = Rect(center-&gt;box.GetCenter().x+(cos(translation*M_PI/180)*200)-(sp.GetWidth()/2),
                     center-&gt;box.GetCenter().y+(sin(translation*M_PI/180)*200)-(sp.GetHeight()/2),
                     sp.GetWidth(), sp.GetHeight());
      }
  
      void Minion::Shoot(Vec2 pos) {
          State::AddObject(new BulletWheel(box.GetCenter().x, box.GetCenter().y, center-&gt;box.GetCenter().GetDX(pos.x),
                                           center-&gt;box.GetCenter().GetDY(pos.y), center-&gt;box.GetCenter().GetDS(pos), 0.3,
                                           translation, center-&gt;box.GetCenter(), "img/minionbullet1.png"));
      }
  
      void Minion::Update(float dt) {
          if(translation &lt; 360)
              translation += 0.03*dt;
          else
              translation += 0.03*dt-360;
          /*rotation = translation-90;*/
          if(rotation &lt; 360)
              rotation += 0.15*dt;
          else
              rotation += 0.15*dt-360;
          box.x = center-&gt;box.GetCenter().x+(200*cos((translation)*M_PI/180))-(box.w/2);
          box.y = center-&gt;box.GetCenter().y+(200*sin((translation)*M_PI/180))-(box.h/2);
      }
  
      void Minion::Render() {
          sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
      }
  
      bool Minion::IsDead() {
          return false;
      }
  
      Bullet::Bullet(float x, float y, float dx, float dy, float maxDistance, float speed, std::string sprite) {
          sp = Sprite(sprite);
          box = Rect(x-(sp.GetWidth()/2), y-(sp.GetHeight()/2), sp.GetWidth(), sp.GetHeight());
          Bullet::speed = Vec2(speed*(dx/maxDistance), speed*(dy/maxDistance));
          distanceLeft = maxDistance;
          rotation = atan2(dy, dx)*(180/M_PI);
      }
  
      void Bullet::Update(float dt) {
          if(distanceLeft &gt; 0) {
              box.x += speed.x*dt;
              box.y += speed.y*dt;
              distanceLeft -= pow(pow(speed.x*dt,2)+pow(speed.y*dt,2),0.5);
          }
      }
  
      void Bullet::Render() {
          sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
      }
  
      bool Bullet::IsDead() {
          return (distanceLeft &lt; 1) ? true : false;
      }
  
      Bullet* Bullet::get() {
          return this;
      }
  
      BulletWheel::BulletWheel(float x, float y, float dx, float dy, float maxDistance, float speed, float arcOffset, Vec2 center, std::string sprite) {
          sp = Sprite(sprite);
          sp.SetScaleX(2);
          sp.SetScaleY(2);
          box = Rect(x-(sp.GetWidth()/2), y-(sp.GetHeight()/2), sp.GetWidth(), sp.GetHeight());
          BulletWheel::speed = Vec2(speed*(dx/maxDistance), speed*(dy/maxDistance));
          distanceLeft = maxDistance;
          rotation = atan2(dy, dx)*(180/M_PI);
          translation = arcOffset;
          BulletWheel::center = center;
      }
  
      void BulletWheel::Update(float dt) {
          if(translation &lt; 360)
              translation += 0.1*dt;
          else
              translation += 0.1*dt-360;
          if(distanceLeft &gt; 0.01) {
              center.x += speed.x*dt;
              center.y += speed.y*dt;
              box.x = center.x+(200*cos((translation)*M_PI/180))-(box.w/2);
              box.y = center.y+(200*sin((translation)*M_PI/180))-(box.h/2);
              distanceLeft -= pow(pow(speed.x*dt,2)+pow(speed.y*dt,2),0.5);
          }
      }
  
      void BulletWheel::Render() {
          sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
      }
  
      bool BulletWheel::IsDead() {
          return distanceLeft &lt; 1;
      }
  
      BulletWheel* BulletWheel::get() {
          return this;
      }
  </code></pre>
  
  <p>and its header file is: 
      #ifndef GAMEOBJECT_H_
      #define GAMEOBJECT_H_</p>
  
  <pre><code>#include "Sprite.h"
  #include "Rect.h"
  #include "Vec2.h"
  #include &lt;queue&gt;
  #include &lt;vector&gt;
  #include &lt;cmath&gt;
  #include &lt;ctime&gt;
  
  class GameObject{
  private:
  
  public:
      virtual ~GameObject();
      virtual void Update(float dt) = 0;
      virtual void Render() = 0;
      virtual bool IsDead() = 0;
      virtual GameObject* get();
      int rotation = 0;
      int translation = 0;
      Sprite sp = Sprite();
      Vec2 speed = Vec2();
      Rect box = Rect();
  };
  
  class Minion : public GameObject {
  private:
      GameObject* center;
  
  public:
      Minion(GameObject* minionCenter, float arcOffset, float minionSize = 1);
      ~Minion();
      void Shoot(Vec2 pos);
      void Update(float dt);
      void Render();
      bool IsDead();
      Minion* get();
  };
  
  class Bullet : public GameObject {
  private:
      float distanceLeft;
  public:
      Bullet(float x, float y, float dx, float dy, float maxDistance, float speed, std::string sprite);
      void Update(float dt);
      void Render();
      bool IsDead();
      Bullet* get();
  };
  
  class BulletWheel : public GameObject {
  private:
      float distanceLeft;
      Vec2 center;
  public:
      BulletWheel(float x, float y, float dx, float dy, float maxDistance, float speed, float arcOffset, Vec2 center, std::string sprite);
      void Update(float dt);
      void Render();
      bool IsDead();
      BulletWheel* get();
  };
  
  #endif /* GAMEOBJECT_H_ */
  </code></pre>
  
  <p>There are the virtual functions of GameObject, declared inside Alien.cpp:</p>
  
  <pre><code>void Alien::Update(float dt) {
      if(rotation &gt; 0)
          rotation -= 0.1*dt;
      else
          rotation -= 0.1*dt+360;
      if(InputManager::GetInstance().MousePress(RIGHT_MOUSE_BUTTON)) {
          taskQueue.push(Action(Action::MOVE,(InputManager::GetInstance().GetMouseX() + Camera::GetInstance().pos.x - (box.w/2)),
                                             (InputManager::GetInstance().GetMouseY() + Camera::GetInstance().pos.y - (box.h/2))));
      }
      if(InputManager::GetInstance().MousePress(LEFT_MOUSE_BUTTON)) {
          taskQueue.push(Action(Action::SHOOT,(InputManager::GetInstance().GetMouseX() + Camera::GetInstance().pos.x),
                                              (InputManager::GetInstance().GetMouseY() + Camera::GetInstance().pos.y)));
      }
      if(taskQueue.size() &gt; 0) {
          Vec2 pos = taskQueue.front().pos;
          if(taskQueue.front().type == Action::MOVE) {
              float cos = (box.GetDX(pos.x)/box.GetDS(pos));
              float sin = (box.GetDY(pos.y)/box.GetDS(pos));
              if(cos != cos) {
                  cos = 0;
              }
              if(sin != sin) {
                  sin = 0;
              }
              if((box.x+speed.x*cos*dt &gt; pos.x &amp;&amp; pos.x &gt; box.x) || (box.x+speed.x*cos*dt &lt; pos.x &amp;&amp; pos.x &lt; box.x)) {
                  box.x = pos.x;
              }
              else {
                  box.x += speed.x*cos*dt;
              }
              if((box.y+speed.y*sin*dt &gt; pos.y &amp;&amp; pos.y &gt; box.y) || (box.y+speed.y*sin*dt &lt; pos.y &amp;&amp; pos.y &lt; box.y)) {
                  box.y = pos.y;
              }
              else {
                  box.y += speed.y*sin*dt;
              }
              if(box.x == pos.x &amp;&amp; box.y == pos.y) {
                  taskQueue.pop();
              }
          }
          else {
              for(unsigned i = 0; i &lt; minionArray.size(); i++) {
              minionArray.at(i).Shoot(pos);
              taskQueue.pop();
              }
          }
      }
      for(unsigned i = 0; i &lt; minionArray.size(); i++) {
          minionArray.at(i).Update(dt);
      }
  }
  
  void Alien::Render() {
      sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
      if(minionArray.size() &gt; 0) {
          for(unsigned i = 0; i &lt; Alien::minionArray.size(); i++) {
              minionArray.at(i).Render();
          }
      }
  }
  
  bool Alien::IsDead() {
      return (Alien::hitpoints &lt;= 0);
  }
  </code></pre>
  
  <p>EDIT: the destructor of Alien was missing.</p>