【问题标题】:Template Factory Pattern in C++C++ 中的模板工厂模式
【发布时间】:2011-03-03 19:27:10
【问题描述】:

我正在尝试创建一个可以传入类型的工厂,而不是为类型硬编码。但是,当我尝试将类型添加到类型 .cpp 文件中的工厂时,我会收到链接器错误。例如,他是我目前遇到的链接器错误。

1>RandomClass.obj:错误 LNK2019:函数中引用的未解析外部符号“public:short __thiscall TemplatedFactory::AddType(char const *)”(??$AddType@VRandomClass@@@TemplatedFactory@@QAEFPBD@Z) "void _cdecl 'private: static short RandomClass::ID''的动态初始化器(void)" (??_E?ID@RandomClass@@0FA@@YAXXZ)

我试图使测试用例尽可能小,虽然它确实跨越了五个文件,但它们非常小

BaseClass.h : http://codepad.org/MhZMw7t0

#pragma once
class BaseClass{ };

RandomClass.h : http://codepad.org/xoObzP8G

#pragma once
#include "BaseClass.h"
class RandomClass : public BaseClass
{
private:
    static short ID;

public:
    RandomClass();
    virtual ~RandomClass();
};

TemplatedFactory.h : http://codepad.org/qkcTBw24

#pragma once
#include <map>
using std::map;
#include "BaseClass.h"

template<typename Type> BaseClass* createType() { return new Type; }

class TemplatedFactory
{
private:
    typedef BaseClass* (*ComponentFactoryFuncPtr)();
    typedef map<const char*, ComponentFactoryFuncPtr> map_type;

    map_type m_Map;

public:
    static TemplatedFactory &GetInstance();

    template<typename Type>
    short AddType(const char* componentName);
};

RandomClass.cpp : http://codepad.org/ALoF3Ysb

#include "RandomClass.h"
#include "TemplatedFactory.h"

short RandomClass::ID = TemplatedFactory::GetInstance().AddType<RandomClass>("RandomClass");

RandomClass::RandomClass() { }

RandomClass::~RandomClass() { }

TemplatedFactory.cpp : http://codepad.org/iqgNqa6H

#include "TemplatedFactory.h"

TemplatedFactory &TemplatedFactory::GetInstance()
{
    static TemplatedFactory instance;
    return instance;
}

template<typename Type>
short TemplatedFactory::AddType(const char* componentName)
{
    ComponentFactoryFuncPtr function = &createType<Type>;
    m_Map.insert(std::make_pair(componentName, function));

    return 0;
}

如果我移动,我可以删除链接器错误

short RandomClass::ID = TemplatedFactory::GetInstance().AddType<RandomClass>("RandomClass");

从 RandomClass.cpp 到 TemplatedFactory.cpp,但是,我希望在 RandomClass.cpp 中有声明。有谁知道解决这个问题的方法或者更好的设计(不使用外部库)。

【问题讨论】:

  • 真正的BaseClass 至少有一个虚拟析构函数,对吧?
  • 如果为 RandomClass 添加一个实现到 TemplatedFactory.cpp 会发生什么?尝试将静态类变量链接到动态实现会成为问题。

标签: c++ design-patterns templates metaprogramming factory-pattern


【解决方案1】:

如果没有export,模板函数的定义和声明就不能相互分离,您的编译器可能不支持。您需要将TemplateFactory::AddType 定义移动到标题中。

【讨论】:

  • 有趣,如果我不能使用“导出”,有没有更好的设计模式可以使用?
  • 不,没有更好的“模式”可以使用。模板函数总是只在头文件中实现。这样做不会被人反对。
  • 在 TemplateFactory.h 的 Header 中还是在 RandomClass.h 的 Header 中?如果我可以在 RandomClass.h 标头中这样做也可以,即使它带有某种静态 const short
  • TemplatedFactory::AddType 实现需要移动到 TemplatedFactory.h。无论如何,将其移至 RandomClass.h 是没有意义的。你可以从任何地方调用TemplatedFactory::AddType,只是不能在声明之外定义它。
  • 哦,我明白了,如果我只是将“TemplatedFactory::AddType”函数移动到 TemplatedFactory.h,那么我可以保留“short RandomClass::ID = TemplatedFactory::GetInstance().AddType("随机类");"在我的 RandomClass.cpp ...谢谢你的帮助
【解决方案2】:

您不能将类模板的实现放在 cpp 文件中 在http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14上查看一些“作弊”技术

【讨论】:

  • 从技术上讲,您可以使用外部模板来实现。但这并没有得到 C++ 编译器的广泛支持。
  • 有趣,如果我不能使用“导出”,有没有更好的设计模式可以使用?
  • @VladLazarenko 如果您的意思是外部模板,那么它是关于显式实例化而不是类模板成员的实现。无法使用外部模板将模板 short TemplatedFactory::AddType(const char* componentName) 放置到 TemplatedFactory.cpp – Oleg Svechkarenko 7 分钟前
  • 你是对的,你不能在 cpp 中使用通用 impl ...好吧,除非你将它包含在标题中:-)))
  • Vlad:在 TemplateFactory.h 的 Header 中还是在 RandomClass.h 的 Header 中?如果我可以在 RandomClass.h 标头中这样做也可以,即使它带有某种静态 const short
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多