0

所以我的 ResourceManager 类对于我正在使用 c++ 进行的游戏有一些问题。所以我试图从我的常规 addImage 函数中创建一个模板函数,这样它也会添加声音,但是我遇到了一些我无法真正处理的错误,你们能帮帮我吗?:D

.hpp

#ifndef RESOURCE_MANAGER_HPP
#define RESOURCE_MANAGER_HPP

#include "Image.cpp"
#include "SoundBuffer.cpp"
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

typedef std::map<std::string, sz::Image*> ImagesContainer;
typedef std::map<std::string, sz::Image*>::iterator ImagesContainerIt;
typedef std::map<std::string, sz::SoundBuffer*> SoundsContainer;
typedef std::map<std::string, sz::SoundBuffer*>::iterator SoundsContainerIt;
typedef std::map<std::string, sf::Music*> MusicContainer;
typedef std::map<std::string, sf::Music*>::iterator MusicContainerIt;

namespace sz
{
        //      meanwhile this class is only for images, need to edit later for
        //      it to be also able to load sounds, etc...
        class ResourceManager{
                private:
                ResourceManager() {};
                ResourceManager(ResourceManager const&) {};
                static ResourceManager *rm;
                // add functions and variables here
                ImagesContainer imagesContainer;
                SoundsContainer soundsContainer;
                MusicContainer  musicContainer;
                template <class type>
                void AddNew(std::string imagePath);

                public:
                static ResourceManager *Instance();
                // add functions here
                template <class type>
                type *Get(std::string imagePath);
        };
}

#endif

.cpp

#include "ResourceManager.hpp"
#include <typeinfo>

namespace sz
{
        ResourceManager *ResourceManager::rm = NULL;  

        ResourceManager *ResourceManager::Instance()
        {
           if (!rm)
                  rm = new ResourceManager;

           return rm;
        }

        template <class type>
        void ResourceManager::AddNew(std::string filePath)
        {
                type *item = new type(filePath);
                if(typeid(type) == typeid(sz::Image))
                        imagesContainer[filePath] = item;
                else if(typeid(type) == typeid(sz::SoundBuffer))
                        soundsContainer[filePath] = item;
                else
                        return;
        }

        template <class type>
        type *ResourceManager::Get(std::string filePath)
        {
                if(typeid(type) == typeid(sz::Image))
                {
                        ImagesContainerIt it = imagesContainer.find(filePath);
                        if(it == imagesContainer.end())
                        {
                                AddNew<type>(filePath);
                        }
                        it = imagesContainer.find(filePath);
                        return it->second;
                }

                else if(typeid(type) == typeid(sz::SoundBuffer))
                {
                        SoundsContainerIt it = soundsContainer.find(filePath);
                        if(it == soundsContainer.end())
                        {
                                AddNew<type>(filePath);
                        }
                        it = soundsContainer.find(filePath);
                        return it->second;
                }

                else
                        return NULL;
        }
}

错误@_@

g++ -Wall -c "Sprite.cpp" (in directory: /home/gannash/Desktop/Open Heroes/Engine)
In file included from Sprite.cpp:2:0:
ResourceManager.cpp: In member function ‘type* sz::ResourceManager::Get(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’:
Sprite.cpp:10:65:   instantiated from here
ResourceManager.cpp:50:15: error: cannot convert ‘sz::SoundBuffer*’ to ‘sz::Image*’ in return
ResourceManager.cpp: In member function ‘void sz::ResourceManager::AddNew(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’:
ResourceManager.cpp:36:5:   instantiated from ‘type* sz::ResourceManager::Get(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’
Sprite.cpp:10:65:   instantiated from here
ResourceManager.cpp:23:4: error: cannot convert ‘sz::Image*’ to ‘std::map<std::basic_string<char>, sz::SoundBuffer*>::mapped_type {aka sz::SoundBuffer*}’ in assignment
ResourceManager.cpp: In member function ‘type* sz::ResourceManager::Get(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’:
ResourceManager.cpp:55:2: warning: control reaches end of non-void function [-Wreturn-type]
Compilation failed.
4

3 回答 3

0

好的,这是我查看代码和错误消息后的想法。

你不能像这样从同一个函数返回图像和声音。它们是个体类型。您必须指定要返回的类型。当您将 if/else 放入模板中时,它仍然会检查它是否可以返回所有这些类型,这将失败。

您必须返回 Image 和 Sound 都继承自的 BaseClass*(或任何您想调用的名称)。

于 2012-04-16T12:06:32.043 回答
0

“编译时 if”是通过模板部分特化完成的。但在这里它甚至不需要:

template<typename type> struct Container {
  static std::map<std::string, type*> container;
};
std::map<std::string, sz::Image*>& ImagesContainer = Container<sz::Image>::container;
// etc...
template <class type>
void ResourceManager::AddNew(std::string filePath)
{
  type *item = new type(filePath);
  Container<type>::container[filePath] = item;
}
于 2012-04-16T14:56:53.220 回答
0

必须为编译器完全定义模板化函数才能使用它们。这意味着您必须将这些函数的主体从源文件移动到头文件。

编辑:

您必须检查如何使用模板类。例如,请参阅此错误消息:

ResourceManager.cpp:50:15:错误:无法将 'sz::SoundBuffer*' 转换为 'sz::Image*' 作为回报

除非sz::SoundBuffer继承自sz::Image您,否则类型之间不匹配。

于 2012-04-16T11:56:59.613 回答