未定义的引用,用于从工厂类创建对象名称

时间:2014-09-11 18:01:18

标签: c++ macros factory-pattern

宏类通过调用CREATE_MAPPER("HelloMapper");在main函数中创建对象。 Mapper.h在class_register.h中将对象注册到工厂类到宏,如下例所示

class_register.h

#ifndef COMMON_BASE_CLASS_REGISTER_H_
#define COMMON_BASE_CLASS_REGISTER_H_

#include <map>
#include <string> 
enter code here

#define CLASS_REGISTER_DEFINE_REGISTRY(register_name, base_class_name) \
class ObjectCreatorRegistry_##register_name { \
public: \
typedef base_class_name* (*Creator)(); \
\
ObjectCreatorRegistry_##register_name() \
: m_default_creator(NULL) {} \
~ObjectCreatorRegistry_##register_name() {} \
\
void SetDefaultCreator(Creator creator) { \
m_default_creator = creator; \
} \
\
void AddCreator(std::string entry_name, Creator creator) { \
m_creator_registry[entry_name] = creator; \
} \
\
base_class_name* CreateObject(const std::string& entry_name); \
\
private: \
typedef std::map<std::string, Creator> CreatorRegistry; \
Creator m_default_creator; \
CreatorRegistry m_creator_registry; \
}; \
\
inline ObjectCreatorRegistry_##register_name& \
GetRegistry_##register_name() { \
static ObjectCreatorRegistry_##register_name registry; \
return registry; \
} \
\
class DefaultObjectCreatorRegister_##register_name { \
public: \
DefaultObjectCreatorRegister_##register_name( \
ObjectCreatorRegistry_##register_name::Creator creator) { \
GetRegistry_##register_name().SetDefaultCreator(creator); \
} \
~DefaultObjectCreatorRegister_##register_name() {} \
}; \
\
class ObjectCreatorRegister_##register_name { \
public: \
ObjectCreatorRegister_##register_name( \
const std::string& entry_name, \
ObjectCreatorRegistry_##register_name::Creator creator) { \
GetRegistry_##register_name().AddCreator(entry_name, \
creator); \
} \
~ObjectCreatorRegister_##register_name() {} \
}

#define CLASS_REGISTER_IMPLEMENT_REGISTRY(register_name, base_class_name) \
base_class_name* ObjectCreatorRegistry_##register_name::CreateObject( \
const std::string& entry_name) { \
Creator creator = m_default_creator; \
CreatorRegistry::const_iterator it = \
m_creator_registry.find(entry_name); \
if (it != m_creator_registry.end()) { \
creator = it->second; \
} \
\
if (creator != NULL) { \
return (*creator)(); \
} else { \
return NULL; \
} \
}

#define CLASS_REGISTER_DEFAULT_OBJECT_CREATOR(register_name, \
base_class_name, \
class_name) \
base_class_name* DefaultObjectCreator_##register_name##class_name() { \
return new class_name; \
} \
DefaultObjectCreatorRegister_##register_name \
g_default_object_creator_register_##register_name##class_name( \
DefaultObjectCreator_##register_name##class_name)

#define CLASS_REGISTER_OBJECT_CREATOR(register_name, \
base_class_name, \
entry_name_as_string, \
class_name) \
base_class_name* ObjectCreator_##register_name##class_name() { \
return new class_name; \
} \
ObjectCreatorRegister_##register_name \
g_object_creator_register_##register_name##class_name( \
entry_name_as_string, \
ObjectCreator_##register_name##class_name)

#define CLASS_REGISTER_CREATE_OBJECT(register_name, entry_name_as_string) \
GetRegistry_##register_name().CreateObject(entry_name_as_string)

#endif // COMMON_BASE_CLASS_REGISTER_H_

mapper.h(接口定义):

#include "class_register.h"
 class Mapper {
 };

 CLASS_REGISTER_DEFINE_REGISTRY(mapper_register, Mapper);

 #define REGISTER_MAPPER(mapper_name) \
 CLASS_REGISTER_OBJECT_CREATOR( \
 mapper_register, Mapper, #mapper_name, mapper_name) \

 #define CREATE_MAPPER(mapper_name_as_string) \
 CLASS_REGISTER_CREATE_OBJECT(mapper_register, mapper_name_as_string)`

hello_mapper.cc(Mapper的一个实现):

 #include "mapper.h"
 class HelloMapper : public Mapper {
 };
 REGISTER_MAPPER(HelloMapper);

mapper_user.cc(所有已注册地图制作者的最终用户):

 #include "mapper.h"
 CLASS_REGISTER_IMPLEMENT_REGISTRY(mapper_register, Mapper);
 int main(){
   Mapper* mapper = CREATE_MAPPER("HelloMapper");
 }

编译代码后,按照

等命令行执行

g++ -g -o mapper mapper_user.cc mapper.h class_register.h hello_mapper.cc

G ++在编译完源代码后显示错误。

mapper_user.cc:line: undefined reference to ObjectCreatorRegistry_mapper_register::CreateObject(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'

为什么main()函数不能在宏中对ObjectCreatorRegistry_mapper_register进行未定义的引用?

2 个答案:

答案 0 :(得分:2)

鱼:

  

*请注意,在OP编辑添加此建议修复的问题之前,已给出了此答案。

编译错误是由于缺少方法ObjectCreatorRegistry_mapper_register::CreateObject()。仅在使用CLASS_REGISTER_IMPLEMENT_REGISTRY()时才会创建此选项。您需要将此行添加到适当的源文件中:

CLASS_REGISTER_IMPLEMENT_REGISTRY(mapper_register, Mapper);

如何钓鱼:

错误消息看起来难以辨认,但如果您专注于类名和方法,则应该更容易理解:

  

mapper_user.cc:line: undefined reference to
ObjectCreatorRegistry_mapper_register::CreateObject(
  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

方法 CreateObject 未定义引用消息表明该方法具有原型,但未定义。搜索CreateObject的宏会显示使用CLASS_REGISTER_IMPLEMENT_REGISTRY宏创建定义。

在无关的说明中......

不要在编译行上指定头文件。

g++ -g -o mapper mapper_user.cc hello_mapper.cc

答案 1 :(得分:0)

{p> base_class_name* ObjectCreatorRegistry_##register_name::CreateObject(CLASS_REGISTER_DEFINE_REGISTRY声明。这是由mapper.h编译的

它应该由宏CLASS_REGISTER_IMPLEMENT_REGISTRY实现。但没有人称之为....所以ObjectCreatorRegistry_##register_name类函数没有实现!