2016-12-02 41 views
0

我想創建一個C++/QT類模板的工廠,可以用鑰匙用類模板

創建不同的對象的靜態方法奇怪的問題,所以我創建了一個類名爲CFactory,將創建CComponent這是派生從CBaseComponent

Factory.h

#ifndef FACTORY_H 
#define FACTORY_H 
#include "Header.h" 

template <class Object, class Key = QString> class Factory 
{ 
     static QMap<Key, Object*> m_map; 
    public: 
     static void Register(Key key, Object* obj); 
     Object* Create(const Key& key); 
}; 

#endif // FACTORY_H 

Factory.cpp

#include "factory.h" 
template <class Object, class Key> QMap<Key, Object*> Factory<Object, Key>::m_map = QMap<Key, Object*>();           
template <class Object, class Key> void Factory<Object, Key>::Register(Key key, Object* obj) 
{ 
    if (m_map.find(key) == m_map.end()) 
    { 
    m_map[key] = obj; 
    } 
} 
template <class Object, class Key> Object* Factory<Object, Key>::Create(const Key& key) 
{ 
    Object* tmp = 0; 
    typename QMap<Key, Object*>::iterator it = m_map.find(key); 
    if (it != m_map.end()) 
    { 
     tmp = ((*it).second)->Clone(); 
    } 
    return tmp; 
} 

BaseComponent.h

#ifndef BASECOMPONENT_H 
#define BASECOMPONENT_H 

#include "Header.h" 
class CBaseComponent 
{ 
    public: 
     CBaseComponent(){}; 
     ~CBaseComponent(){}; 
}; 

#endif 

Component.h

#ifndef COMPONENT_H 
    #define COMPONENT_H 

    #include "BaseComponent.h" 
    class CComponent : 
    public CBaseComponent 
    { 
     public: 
     CComponent(){}; 
    ~CComponent(){}; 
    }; 

    #endif 

Main.cpp的

#include "templatefactorydemo.h" 
#include <QtWidgets/QApplication> 
#include "Factory.h" 
#include "Component.h" 
int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    Factory<CBaseComponent> fac; 
    Factory<CBaseComponent>::Register(QString("CComponent"), new CComponent); 
    CBaseComponent *c=fac.Create("CComponent"); 
    return a.exec(); 
} 

當我建立這個錯誤我得到(譯自法文):

錯誤LNK2019無法解析的外部符號「publi c:static void __cdecl Factory :: Register(class QString,class CBaseComponent *)「 (?Register @?$ Factory @ VCBaseComponent @@ VQString @@@@ SAXVQString @@ PAVCBaseComponent @@@ Z) 在函數中引用 _main TemplateFactoryDe​​mo d:\ TRV \ TemplateFactoryDe​​mo \ main.obj 1

+0

你能把它翻譯成英文嗎?我不確定編譯器在說什麼。我猜這是一個鏈接錯誤,但我不確定。 – Cornstalks

+0

http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – lsbbo

回答

1

你必須在頭文件來定義模板的成員函數。基本上移動從您的Factory.cppFactory.h的所有內容。

((*it).second)->Clone();也莫名其妙腥,可能是你的事實,std::map等人使用pair<const K, V>作爲value_type,這是不是QMap的情況混爲一談。你可能的意思是(*it)->Clone()it.value()->Clone()

+0

謝謝您的回覆也解決了這個問題,但我不明白爲什麼我有將Factory.cpp中的所有內容移至Factory.h?你能解釋更多嗎?我的代碼是什麼? –

+0

C++編譯器分別編譯每個「單元」,其中.cpp文件就是這樣一個單元。 此外,模板化函數僅根據需求爲其請求的具體類型生成。當編譯Factory.cpp時,不會生成任何內容,因爲Factory.cpp或其包含的頭文件中都沒有使用模板化函數。當main.cpp中被編譯,編譯器只知道的main.cpp和所有包含的文件,其中不包括Factory.cpp,所以沒有從Factory.cpp功能定義實際上是在主要請求的具體類型產生。 CPP。 – E4z9

+0

函數_declarations_是通過生成的,因爲它們在Factory.h中。這就是main.cpp _compiles_的原因,但_linker_在鏈接可執行文件時抱怨缺少這些函數的定義。 – E4z9