2015-12-20 171 views
-4

首先,我想說我最初是通過C++ Primer學習C++的,但是因爲我想了解一些關於SDL lib的知識,我決定從Shaun獲得「SDL-Game-Development」書籍米切爾。C++ - 虛擬繼承

我現在在第3章中,我對虛擬繼承有一些問題。我知道它是如何工作的,但我無法在程序中找到問題。

錯誤:

||=== Build: Debug in test (compiler: GNU GCC Compiler) ===| 
C:\Users\Documents\test - Kopie (2)\game.cpp||In member function 'void Game::render()':| 
C:\Users\Documents\test - Kopie (2)\game.cpp|78|error: no matching function for call to 'GameObject::draw(SDL_Renderer*&)'| 
C:\Users\Documents\test - Kopie (2)\game.cpp|78|note: candidate is:| 
C:\Users\Documents\test - Kopie (2)\GameObject.h|11|note: virtual void GameObject::draw()| 
C:\Users\Documents\test - Kopie (2)\GameObject.h|11|note: candidate expects 0 arguments, 1 provided| 
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| 

我知道我有一個說法太多,但遊戲對象有2個派生類,玩家類和敵人類。敵人階級需要爭論,但玩家階層不需要。所以當我刪除參數時,構建器會給我更多的錯誤。

我將列出這裏的所有代碼:

game.h:

#include <SDL.h> 
#include <SDL_image.h> 
#include <iostream> 
#include <vector> 
#include "Player.h" 

using namespace std; 

class Game 
{ 
public: 

bool init(const char* title, int xpos, int ypos, int width, int height, int flags); 
void render(); 
void update(); 
void handleEvents(); 
void clean(); 
bool running() { return m_bRunning; } 
SDL_Renderer* getRenderer() const { return m_pRenderer; } 
std::vector<GameObject*> m_gameObjects; 

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

private: 
Game() {} 

bool m_bRunning; 
SDL_Window* m_pWindow; 
SDL_Renderer* m_pRenderer; 
SDL_Texture* m_pTexture; // the new SDL_Texture variable 
int m_currentFrame; 
GameObject* m_go; 
GameObject* m_player; 
GameObject* m_enemy; 
static Game* s_pInstance; 

}; 

game.cpp:

#include <SDL.h> 
#include <iostream> 
#include "game.h" 
#include <SDL_image.h> 
#include <vector> 

using namespace std; 

bool Game::init(const char* title, int xpos, int ypos, int width, 
int height, int flags) 
{ 
// attempt to initialize SDL 
if(SDL_Init(SDL_INIT_EVERYTHING) == 0) 
{ 

m_gameObjects.push_back(new Player(new LoaderParams(100, 100, 128, 82, "animate"))); 
m_gameObjects.push_back(new Enemy(new LoaderParams(300, 300, 128, 82, "animate"))); 

cout << "SDL init success\n"; 
// init the window 
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags); 
if(m_pWindow != 0) // window init success 
{ 
cout << "window creation success\n"; 
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0); 
if(m_pRenderer != 0) // renderer init success 
{ 
cout << "renderer creation success\n"; 
SDL_SetRenderDrawColor(m_pRenderer, 255,0,0,255); 

if(!TextureManager::Instance()->load("explosion-sprite.png", "animate", m_pRenderer)) 
{ 
return false; 
} 

} 
else 
{ 
cout << "renderer init fail\n"; 
return false; // renderer init fail 
} 
} 
else 
{ 
cout << "window init fail\n"; 
return false; // window init fail 
} 
} 
else 
{ 
cout << "SDL init fail\n"; 
return false; // SDL init fail 
} 
cout << "init success\n"; 
m_bRunning = true; // everything inited successfully, 
return true; 
} 

void Game::render() 
{ 
SDL_RenderClear(m_pRenderer); // clear the renderer to 

for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++) 
{ 
m_gameObjects[i]->draw(m_pRenderer); 
} 

SDL_RenderPresent(m_pRenderer); // draw to the screen 
} 

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

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

void Game::update() 
{ 
for(std::vector<GameObject*>::size_type i = 0; i != 
m_gameObjects.size(); i++) 
{ 
m_gameObjects[i]->update(); 
} 
} 

Game* Game::s_pInstance = 0; 

TextureManager.h:

#include <SDL.h> 
#include <SDL_image.h> 
#include <iostream> 
#include <map> 
#include "Loaderparams.h" 

using namespace std; 

class TextureManager{ 
public: 
bool load(string filename, string id, SDL_Renderer* Renderer); 

void draw(string id, int x, int y, int width, int height, SDL_Renderer* Renderer, SDL_RendererFlip = SDL_FLIP_NONE); 

void drawFrame(string id, int x, int y, int width, int height, int row, int frame, SDL_Renderer* Renderer, SDL_RendererFlip flip = SDL_FLIP_NONE); 

static TextureManager* Instance(); 

private: 
TextureManager() {} 
map<string, SDL_Texture*> textureMap; 
}; 

TextureManager .cpp:

#include <SDL.h> 
#include <iostream> 
#include "TextureManager.h" 
#include <SDL_image.h> 

using namespace std; 

bool TextureManager::load(string filename, string id, SDL_Renderer* Renderer){ 
SDL_Surface* surf = IMG_Load(filename.c_str()); 

if(surf == NULL) 
return false; 

SDL_Texture* text = SDL_CreateTextureFromSurface(Renderer, surf); 
SDL_FreeSurface(surf); 

if(text != 0){ 
textureMap[id] = text; 
return true; 
} 
return false; 
} 



void TextureManager::draw(string id, int x, int y, int width, int height, SDL_Renderer* Renderer, SDL_RendererFlip flip){ 

SDL_Rect source; 
SDL_Rect destination; 

source.x = 0; 
source.y = 0; 
destination.w = source.w = width; 
destination.h = source.h = height; 

destination.x = x; 
destination.y = y; 

SDL_RenderCopyEx(Renderer, textureMap[id], &source, &destination, 0, 0, flip); 
} 



void TextureManager::drawFrame(string id, int x, int y, int width, int height, int row, int frame, SDL_Renderer* Renderer, SDL_RendererFlip flip){ 

SDL_Rect source; 
SDL_Rect destination; 

source.x = width * frame; 
source.y = height * row; 

destination.w = source.w = width; 
destination.h = source.h = height; 

destination.x = x; 
destination.y = y; 

SDL_RenderCopyEx(Renderer, textureMap[id], &source, &destination, 0, 0, flip); 
} 

TextureManager* s_pInstance = 0; 

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

player.h:

#include "GameObject.h" 

using namespace std; 

class Player : public SDLGameObject 
{ 
public: 
Player(const LoaderParams* pParams): SDLGameObject(pParams){} 

virtual void draw(); 
virtual void update(); 
virtual void clean(); 
}; 

// Enemy class 
class Enemy : public SDLGameObject 
{ 
public: 
Enemy(const LoaderParams* pParams); 
virtual void draw(); 
virtual void update(); 
virtual void clean(); 
}; 

player.cpp:

#include "Player.h" 

using namespace std; 

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


void Player::draw() 
{ 
SDLGameObject::draw(); // we now use SDLGameObject 
} 


void Player::update() 
{ 
m_x -= 1; 
m_currentFrame = int(((SDL_GetTicks()/100) % 6)); 
} 

void Player::clean() {} 

//ENEMY 

void Enemy::load(int x, int y, int width, int height, string 
textureID) 
{ 
GameObject::load(x, y, width, height, textureID); 
} 


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


void Enemy::update() 
{ 
m_position.setX(m_position.getX() + 1); 
m_position.setY(m_position.getY() + 1); 
m_currentFrame = int(((SDL_GetTicks()/100) % 6)); 
} 

void Enemy::clean(){ 
} 

Gameobject.h:

#include <iostream> 
#include <SDL.h> 
#include "TextureManager.h" 
#include "Vector2D.h" 

using namespace std; 

class GameObject 
{ 
public: 
virtual void draw() = 0; 
virtual void update() = 0; 
virtual void clean() = 0; 
protected: 
GameObject(const LoaderParams* pParams) {} 
virtual ~GameObject() {} 
}; 


class SDLGameObject : public GameObject 
{ 
public: 
SDLGameObject(const LoaderParams* pParams) : 
GameObject(pParams), m_position(pParams->getX(), pParams->getY()) 
{ 
m_width = pParams->getWidth(); 
m_height = pParams->getHeight(); 
m_textureID = pParams->getTextureID(); 
m_currentRow = 1; 
m_currentFrame = 1; 
} 

virtual void draw(); 
virtual void update(); 
virtual void clean(); 
protected: 
Vector2D m_position; 
int m_width; 
int m_height; 
int m_currentRow; 
int m_currentFrame; 
std::string m_textureID; 
}; 

Gameobject.cpp:

#include <iostream> 
#include <SDL.h> 
#include "GameObject.h" 

using namespace std; 

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(){ 
} 


//SDLGameObject 

void SDLGameObject::draw() 
{ 
TextureManager::Instance()->drawFrame(m_textureID, 
(int)m_position.getX(), (int)m_position.getY(), m_width, 
m_height, m_currentRow, m_currentFrame, 
Game::Instance()->getRenderer()); 
} 

還有一個Vector.h但它不是importent的問題

+0

請縮進您的代碼。沒有人會讀這個頭痛。 –

+1

我很確定可以在不影響問題的情況下移除95%的代碼。這將使人們更容易閱讀它,甚至可能導致自己發現錯誤。 –

回答

0

我想你應該在頭文件中添加重載方法簽名了。

virtual void draw(); 
virtual void draw(SDL_Renderer* pRenderer); 

我沒有檢查整個代碼,所以可能還有其他的問題,但特定的錯誤消息表明draw方法與簽名不存在。

請記住cpp文件將被編譯成目標文件,鏈接器是知道該方法存在的人,這就是爲什麼編譯器沒有關於該重載方法的任何信息會抱怨不恰當的簽名。

0
class GameObject 
{ 

    public: 
    virtual void draw() = 0; 
    virtual void update() = 0; 
    virtual void clean() = 0; 
    protected: 
    GameObject(const LoaderParams* pParams) {} 
    virtual ~GameObject() {} 

}; 

只有一個draw()

所以你不能做m_gameObjects[i]->draw(m_pRenderer);

的簽名不匹配。 GameObject類只有一個draw()

請記住,您不能通過繼承來更改虛函數的函數簽名。簽名必須保持不變。