未定义引用`vtable敌人

时间:2019-06-20 17:06:45

标签: c++ sdl

我正在尝试用c ++ / sdl2编写游戏引擎。

将多态性添加到引擎功能时,我得到:

/tmp/ccF9RkLz.o:在函数Enemy::Enemy()': main.cpp:(.text._ZN5EnemyC2Ev[_ZN5EnemyC5Ev]+0x1b): undefined reference to vtable中显示为敌人' collect2:错误:ld返回1退出状态

:使用$ g ++ main.cpp -std = c ++ 98 -fpermissive -Wall -lSDL2 -lSDL2_image编译时

我需要使不同的函数成为虚拟的还是纯虚拟的,或者删除/添加定义?

我尝试在敌人的类中定义draw函数,但仍然遇到相同的错误。

Main.cpp

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include "TextureManager.h"
#include "TextureManager.cpp"
#include "GameObject.h"
#include "GameObject.cpp"
#include "Player.h"
#include "Player.cpp"
#include "Game.h"
#include "Game.cpp"
#include "Enemy.h"
#include "Enemy.cpp"

int main(int argc, char * args[])
{
Game * g_game = new Game;

g_game->init("Chapter 1", 100,100,640,480,false);

while(g_game->running())
{
g_game->handleEvents();
g_game->update();
g_game->render();

SDL_Delay(10);

}
g_game->clean();

return 0;

}

Enemy.h

#ifndef __Enemy__
#define __Enemy__

#include "GameObject.h"

class Enemy : public GameObject
{
public:
void load(int x, int y, int width, int height, std::string textureID);
void draw(SDL_Renderer* pRenderer);
void update();
void clean();
};

#endif // defined __Enemy_h__

Enemy.cpp

#include "Enemy.h"

void Enemy::update()
{
m_y += 1;
m_x += 1;
m_currentFrame = int((SDL_GetTicks() / 100) % 6);
}

void Enemy::draw(SDL_Renderer* pRenderer) 
{
TextureManager::Instance()->drawFrame(m_textureID, m_x, m_y, m_width,               

m_height, m_currentRow,
m_currentFrame, pRenderer);
}

Game.h

#ifndef __Game__
#define __Game__

#include"GameObject.h"

class Game
{
public:
Game() {}
~Game() {}



bool init(const char* title, int xpos, int ypos, int width,
int height, bool fullscreen);
void render();
void update();
void handleEvents();
void clean();
void draw();

// a function to access the private running variable
bool running() {return m_bRunning;}

private:
std::vector<GameObject*> m_GameObjects;
GameObject* m_player;
GameObject* m_enemy1;
GameObject* m_enemy2;
GameObject* m_enemy3;
SDL_Window * m_pWindow;
SDL_Renderer * m_pRenderer;
SDL_Surface * pTempSurface;

int m_currentFrame;

bool m_bRunning;
};

GameObject * m_go;
GameObject * m_player;
#endif /* defined(__Game_h__) */

Game.cpp

#include "Game.h" 
#include "Enemy.h"
#include "GameObject.h"

bool Game::init(const char* title, int xpos, int ypos, int width,

int height, bool fullscreen)
{
m_player = new Player();
m_enemy1 = new Enemy();
m_enemy2 = new Enemy(); 
m_enemy3 = new Enemy();

m_GameObjects.push_back(m_player);
m_GameObjects.push_back(m_enemy1);
m_GameObjects.push_back(m_enemy2);
m_GameObjects.push_back(m_enemy3);

int flags = 0;

if (fullscreen)
{
flags = SDL_WINDOW_FULLSCREEN;
}

    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
    std::cout<<"SDL Init Success\n";
    // init the window
    m_pWindow = SDL_CreateWindow(title, xpos, 
    ypos,width,height,flags);                  
    }
    else
    {
    std::cout<<"Window Init Fail\n";
    return false; //window init fail
    }

    if(m_pWindow != 0) //window init success
    {
    std::cout<<"Window Creation Success\n";
    m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);

        if(m_pRenderer !=0) // render init success
        {
        std::cout<<"Renderer Creation Success\n";
        SDL_SetRenderDrawColor(m_pRenderer, 255,0,0,255);
        }   
        else
        {
        std::cout<<"Renderer Init Fail\n";
        return false; // renderer init fail
        }



}

else
{
std::cout<<"SDL Init Fail\n";
return false; // SDL init fail
}



    //to load                   
    if(!TheTextureManager::Instance()->load("assets/animate-

alpha.png","animate", m_pRenderer))
    {
    return false;
    }

m_go = new GameObject();
m_player = new Player();

m_go->load(100,100,128,82, "animate");
m_player->load(300,300,128,82, "animate");

m_GameObjects.push_back(m_go);
m_GameObjects.push_back(m_player);

GameObject* m_enemy;

m_enemy = new Enemy();
m_enemy ->load(0,0,128,82,"animate");
m_GameObjects.push_back(m_enemy);

std::cout<<"Init success\n";

m_bRunning = true; // everything inited successfully
// start the main loop

return true;

}

void Game::render()
{

SDL_RenderClear(m_pRenderer);


// loop through our objects and draw them

for(std::vector<GameObject*>::size_type i =0; i!=m_GameObjects.size();  

i++)
{
m_GameObjects[i]->draw(m_pRenderer);
}


//to draw
//TheTextureManager::Instance()->draw("animate",0,0, 128, 82,   

m_pRenderer);

//to animate


//TheTextureManager::Instance()->drawFrame
("animate",100,100,128,82,1,
m_currentFrame, m_pRenderer);

//m_go.draw(m_pRenderer);

//m_player.draw(m_pRenderer);

SDL_RenderPresent(m_pRenderer);

}

void Game::update()
{
//m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
//m_go.update();
//m_player.update();

for(std::vector<GameObject*>::size_type i = 0; i !=   

m_GameObjects.size(); i++)
{
m_GameObjects[i]->update();
}

}

void Game::clean()
{
std::cout<<"Cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}




void Game::handleEvents()
{
SDL_Event event;
if(SDL_PollEvent(&event))
{
    switch (event.type)
    {
    case SDL_QUIT:
    m_bRunning = false;
    break;
    }
}
}

void Game::draw()
{
for(std::vector<GameObject*>::size_type i = 0; i != 

m_GameObjects.size(); i++)
{
m_GameObjects[i]->draw(m_pRenderer);
}
}

GameObject.h

#ifndef __GameObject__
#define __GameObject__

//#include <SDL_image.h>
#include "TextureManager.h"

class GameObject
{
public:
virtual void load(int x, int y, int width, int height, std::string   

textureID);
virtual void draw(SDL_Renderer* pRenderer);
virtual void update();
virtual void clean();


protected:

std::string m_textureID;
int m_currentFrame;
int m_currentRow;
int m_x;
int m_y;
int width;
int height;
int m_width;
int m_height;
};

#endif /* defined(__GameObject_h__) */

GameObject.cpp

#include "GameObject.h"

void GameObject::load(int x, int y, int width, int height, std::string 

textureID)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
m_textureID = textureID;

m_currentRow = 1;
m_currentFrame = 1;
}

void GameObject::draw(SDL_Renderer* pRenderer)

{
TextureManager::Instance()->drawFrame(m_textureID, m_x, m_y, m_width, 

m_height, m_currentRow,
m_currentFrame, pRenderer);
}

void GameObject::update()
{
m_x += 1;
}

void GameObject::clean() 
{
// Do Something
}

Player.h

#ifndef __Player__
#define __Player__

#include "GameObject.h"

class Player : public GameObject
{
public:
void load(int x, int y, int width, int height, std::string textureID);

void draw(SDL_Renderer* pRenderer);

void update();

void clean()
{
GameObject::clean();
std::cout<<"clean object\n";
}

};

#endif /*defined Player.h */

Player.cpp

#include "Player.h"

void Player::load(int x, int y, int width, int height, std::string 

textureID)
{
GameObject::load(x,y, width, height, textureID);
}

void Player::draw(SDL_Renderer* pRenderer)
{
GameObject::draw(pRenderer);
}

void Player::update()
{
m_x -=1;
}

TextureManager.h

#ifndef __TextureManager__
#define __TextureManager__

class TextureManager
{
public:
TextureManager(){}

bool load(std::string fileName, std::string id, SDL_Renderer* 

pRenderer);

//draw
void draw(std::string id, int x, int y, int width, int height,   

SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);

// drawframe
void drawFrame(std::string id, int x, int y, int width, int height,   

int currentRow, int currentFrame, SDL_Renderer* pRenderer,  

SDL_RendererFlip flip = SDL_FLIP_NONE);

std::map<std::string, SDL_Texture*> m_textureMap;

static TextureManager *s_pInstance;

static TextureManager* Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new TextureManager();
return s_pInstance;
}

return s_pInstance;
}

private:
~TextureManager(){}

};

typedef TextureManager TheTextureManager;

#endif /* defined(__TextureManager_h__) */

TextureManager.cpp

#include "TextureManager.h"

TextureManager* TextureManager::s_pInstance = 0;

bool TextureManager::load(std::string fileName, std::string id,   

SDL_Renderer* pRenderer)
{
SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());

if(pTempSurface == 0)
{
return false;
printf("IMG_Load Error %s\n", SDL_GetError());
}
else
{
std::cout <<"IMG_Load Success!\n";
}

SDL_Texture* pTexture =
SDL_CreateTextureFromSurface(pRenderer, pTempSurface);

SDL_FreeSurface(pTempSurface);

// everything went ok, add texture to our list
if(pTexture !=0)
{
m_textureMap[id] = pTexture;
return true;
}

// reaching here means something went wrong
return false;
}

void TextureManager::draw(std::string id, int x, int y, int width, int   

height, SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;

srcRect.x =0;
srcRect.y =0;
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x =x;
destRect.y =y;

SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect, 0,  

0, flip);
}

void TextureManager::drawFrame(std::string id, int x, int y, int 

width, int height, int currentRow,
int currentFrame, SDL_Renderer *pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = width * currentFrame;
srcRect.y = height * (currentRow -1);
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;

SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect, 

0,0, flip);
}

$ g ++ main.cpp -std = c ++ 98 -fpermissive -Wall -lSDL2 -lSDL2_image /tmp/ccF9RkLz.o:在函数Enemy::Enemy()': main.cpp:(.text._ZN5EnemyC2Ev[_ZN5EnemyC5Ev]+0x1b): undefined reference to vtable中表示“敌人” collect2:错误:ld返回1退出状态

0 个答案:

没有答案