创建单例时出现错误

SDL2 C++, Error on creating a singleton

本文关键字:错误 单例时 创建      更新时间:2023-10-16

我们遵循Shaun Mitchell的《SDL Game Development》一书,其中使用了SDL2

我们在我们必须创建一个"纹理管理器"的部分。

TextureManager.h

#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <map>
class TextureManager
{
    public:
        bool load(std::string fileName,std::string id,SDL_Renderer* pRenderer);
        void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
        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;

    protected:
    private:
        TextureManager(){}
        static TextureManager* Instance()
        {
            if(s_pInstance == 0)
            {
                s_pInstance = new TextureManager();
                return s_pInstance;
            }
            return s_pInstance;
        }
        typedef TextureManager TheTextureManager;

};

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;
    }
    SDL_Texture* pTexture =
    SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);
    // everything went ok, add the 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);
}

书上说把构造函数设为private,我们照做了。
然后声明静态TextureManager* Instance(),我们不知道该在哪里正确声明,所以我们只是把它放在构造函数之后,然后它还告诉我们要typedef TextureManager。最后它告诉我们声明TextureManager* TextureManager::s_pInstance = 0;on TextureManager.cpp

在执行指令之后,我们遇到了一个错误,上面写着

||=== Build: Debug in Game (compiler: GNU GCC Compiler) ===|
includeTextureManager.h|22|error: 's_pInstance' was not declared in this scope|
includeTextureManager.h|27|error: 's_pInstance' was not declared in this scope|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

问题是:

//
//TextureManager.cpp
//
TextureManager* TextureManager::s_pInstance = 0;

我不知道你为什么要对任何类变量这样做。通常,对于类,您希望将所有变量放在不是函数局部的头文件中,以使其对使用头文件的所有文件可见。

由于变量仅存在于.cpp文件中,因此使用头文件的其他文件都无法看到它,这也是有意义的。因此,就好像您从未在其他文件中声明过它一样,因此,您会得到一个未定义的引用错误:

||=== Build: Debug in Game (compiler: GNU GCC Compiler) ===|
includeTextureManager.h|22|error: 's_pInstance' was not declared in this scope|
includeTextureManager.h|27|error: 's_pInstance' was not declared in this scope|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|