我有一个工厂类,我已经使用了很长一段时间,我试图对其进行一些模板魔术,但它根本行不通。我认为您不需要查看该课程,因为它很大,但是如果您真的认为它相关,那么我将对其进行编辑。无论如何,我有一个这样的设置,我已经永远做了。
class Base :
public Factory<Base>
{
};
class Derived :
public Base
{
static Factory<Base>::DerivedRegister<Derived> m_Reg;
};
Factory<Base>::DerivedRegister<Derived> Derived::m_Reg;
工厂为其提供了静态方法 createInstance(const std::string& name),它将返回已注册对象的实例。DerivedRegister 对象派生自工厂对象,当静态声明时,必须在静态初始化期间构造。这意味着我可以访问它的构造函数中的工厂静态内部,因此我利用它的构造函数在静态初始化期间让工厂可以使用所有已注册的对象。这有效并且已经有一段时间了,但后来我尝试了这样的事情,以便派生类可以避免需要显式地创建静态派生寄存器对象:
class Base :
public Factory<Base>
{
};
template<class TDerived>
class BaseReg :
public Base
{
static Factory<Base>::DerivedRegister<TDerived> m_Reg;
};
template<class TDerived>
Factory<Base>::DerivedRegister<TDerived> BaseReg<TDerived>::m_Reg;
class Derived :
public BaseReg<Derived>
{
};
当我运行程序并尝试创建 Derived 类的实例时,它在工厂中不存在,经过一点涂鸦后,我发现静态 DerivedRegister 永远不会在派生中构造,因为在构造函数中永远不会叫。我觉得这很奇怪。如果 Derived 类不是模板,如何不强制进行静态初始化?当我制作如下所示的虚拟静态对象并在其静态构造中使用 m_Reg 中的方法时,突然 DerivedRegister 构造正确,工厂可以实例化它,毫不费力。
class Base :
public Factory<Base>
{
};
template<class TDerived>
class BaseReg :
public Base
{
protected:
static Factory<Base>::DerivedRegister<TDerived> m_Reg;
};
template<class TDerived>
Factory<Base>::DerivedRegister<TDerived> BaseReg<TDerived>::m_Reg;
class Derived :
public BaseReg<Derived>
{
class RandomClass
{
public:
RandomClass(std::string meh) {}
};
private:
static RandomClass m_Obj;
};
Derived::RandomClass Derived::m_Obj(m_Reg.func());
那么我在这里没有得到关于这个模板类的静态成员初始化的信息吗?它不需要像任何其他非模板对象一样静态初始化对象吗?
编辑:mkay,为了提供一点见解,我将发布 Factory 对象。请注意文字的墙壁。忽略额外的包含,以及多余的 GetNames 和 func 函数,它们只是巫毒代码。
#ifndef FACTORY_H
#define FACTORY_H
// library tools
#include <map>
#include <string>
#include <typeinfo>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <cxxabi.h>
const std::string demangle(const char* name);
template<class base>
class Factory
{
protected:
template<class T>
static base * createT() { return new T;}
typedef std::map<std::string, base*(*)()> map_type;
static map_type& GetMap()
{
static map_type map;
return map;
}
public:
virtual ~Factory(){}
static base * createInstance(const std::string & s)
{
if(!GetMap().count(s))
return nullptr;
typename map_type::iterator it = GetMap().find(s);
return it->second();
}
template <class TDerived>
struct DerivedRegister :
public Factory<base>
{
DerivedRegister()
{
std::string name = demangle(typeid(TDerived).name());
GetMap().insert(std::pair<std::string, base*(*)()>(name, &createT<TDerived>));
}
DerivedRegister(const std::string& name)
{
GetMap().insert(std::pair<std::string, base*(*)()>(name, &createT<TDerived>));
}
std::string func() {return "meh";}
};
static void GetNames(std::vector<std::string>& names)
{
names.clear();
for(auto it = GetMap().begin(); it != GetMap().end(); ++it)
names.push_back(it->first);
}
};
#endif