0

I want to create a class template factory with c++/qt that can create different objects with a key

So I created a class named CFactory that will create CComponent which is derived from 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();
 }

When I build this error I get (translated from French):

Error LNK2019 unresolved external symbol "public: static void __cdecl Factory::Register(class QString,class CBaseComponent *)" (?Register@?$Factory@VCBaseComponent@@VQString@@@@SAXVQString@@PAVCBaseComponent@@@Z) referenced in function _main TemplateFactoryDemo D:\trv\TemplateFactoryDemo\main.obj 1

jaggedSpire
  • 4,423
  • 2
  • 26
  • 52
H.Hassane
  • 3
  • 2
  • Could you translate that to English? I'm not sure what the compiler is saying. I'm guessing it's a linker error but I'm not sure. – Cornstalks Dec 02 '16 at 13:40
  • http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – lsbbo Dec 02 '16 at 14:02

1 Answers1

1

You have to define the templated member functions in the header file. Basically move everything from your Factory.cpp to Factory.h.

((*it).second)->Clone(); is also somehow fishy, probably you are confused by the fact that std::map et al are using pair<const K, V> as value_type, which is not the case for QMap. You probably mean (*it)->Clone() or it.value()->Clone().

E4z9
  • 1,713
  • 9
  • 11
  • Thank you for your reply it resolved the problem, but i dont understand why i have to move everything from Factory.cpp to Factory.h ? can you explain more ? what is the pobleme with my code. – H.Hassane Dec 02 '16 at 15:59
  • The c++ compiler compiles each "unit" separately from each other, where a .cpp file is one such unit. Also, templated functions are generated only by demand for the concrete types they are requested for. When Factory.cpp is compiled, there is nothing generated, because nothing in Factory.cpp or its included headers uses the templated functions. When main.cpp is compiled, the compiler only knows about main.cpp and all its included files, which does not include Factory.cpp, so none of the function definitions from Factory.cpp are actually generated for the concrete types requested in main.cpp. – E4z9 Dec 04 '16 at 09:16
  • The function _declarations_ are generated though, since they are in the included Factory.h. That's the reason why main.cpp _compiles_, but the _linker_ complains about missing definitions for these functions when linking the executable. – E4z9 Dec 04 '16 at 09:22