2012-04-16 115 views
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. 
+0

即時通訊漂亮noob在這一切,所以感謝讓我知道生病盡我所能。 – 2012-04-16 12:01:23

回答

0

好吧,這是我的想法後,看看代碼和錯誤消息。

你不能像這樣的函數返回圖像和聲音。他們是個人類型。你必須指定要返回的類型。當你將if/else放在模板中時,它仍然會檢查它是否可以返回所有這些類型,並且會失敗。

您必須返回Image和Sound繼承的BaseClass *(或任何您想要調用它的)。

+0

噢謝謝男人我明白,我必須爲此做一些polyphormic。非常感謝! – 2012-04-16 12:10:44

+0

-1,錯誤。你不能從一個函數返回'Image'和'Sound',這是真的,但是'Get '和'Get '是兩個函數,所以這個答案背後的邏輯是有缺陷的,真正的問題是'Get '可以'不會返回'Sound',反之亦然,這不是一個大問題,你可以通過選擇'Container'來選擇合適的'Container'來解決這個問題,這是一個編譯時的選擇,因此不需要多態。 – MSalters 2012-04-16 15:00:32

+0

@MSalters不,我相信你是錯的,請再次查看代碼,根據代碼,圖像和聲音從這個函數返回,並且不起作用,因爲它在同一個函數中。 e在同一模板函數中迭代所有聲音和圖像。該函數只能返回一個類型,但它會嘗試返回兩個類型。這就是它失敗的原因。 – mantler 2012-04-16 18:32:02

0

的模板功能已爲編譯器完全定義爲能夠使用它們。這意味着你必須將這些函數的主體從源文件移動到頭文件。

編輯:

你必須檢查你如何使用模板類。例如參見此錯誤消息:

ResourceManager.cpp:50:15: error: cannot convert ‘sz::SoundBuffer*’ to ‘sz::Image*’ in return

除非sz::SoundBuffer繼承sz::Image你有類型之間的不匹配。

+0

對不起人沒有工作,我把所有的代碼移動到頭文件,但錯誤似乎仍然出現:( – 2012-04-16 12:01:49

0

「編譯時如果」通過模板部分專業化完成。但在這裏它甚至不需要:

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; 
} 
+0

以及我不知道這是可能的,但謝謝你隊友我一定會嘗試一下! – 2012-04-17 15:37:33