在使用模板类作为父类时一个关于静态变量的问题
对于钢筋、型钢、混凝土等类似的有限个类型的数据结构,可以统一采用Factory Method设计模式,通过Create(结构类型)静态函数构造。
为此,设计一个模板基类如下:
FiniteClassBase.h
template<</span>typename TClass, typename TType>
class FiniteClassBase
{
public:
virtual ~FiniteClassBase() {};
static std::shared_ptr<</span>TClass> Create(TType type)
{
if (stockVal[type])
{
return stockVal[type];
}
else
{
stockVal[type] = std::shared_ptr<</span>TClass>(new TClass(type));
return stockVal[type];
}
};
protected:
FiniteClassBase() {};
static std::map<</span>TType, std::shared_ptr<</span>TClass>> stockVal;
};
对于一个钢筋类,可以派生自FiniteClassBase:
MateBar.h
class MateBar
: public FiniteClassBase<</span>MateBar, BarType>
{
friend class FiniteClassBase<</span>MateBar, BarType>;
public:
~MateBar();
double GetFy()const { return fy; };
private:
MateBar(BarType type);
double fy;
};
其中BarType为枚举类型, enum class BarType { HPB300, HRB335, HRB400, HRB500 };
很简单的一个思路,但是在使用时要注意一下问题。
1、声明有元类,friend class FiniteClassBase<</span>MateBar, BarType>,这样基类才能访问其构造函数。
2、在MateBar的cpp文件中要做如下声明:
//! 显式实例化,否则调用Create时会提示找不到符号
template class cy::FiniteClassBase<</span>cy::MateBar, cy::BarType>;
//! 模板静态变量的初始化,否则会提示找不到符号
std::map<</span>BarType, std::shared_ptr<</span>MateBar>> FiniteClassBase<</span>MateBar, BarType>::stockVal;
至于原因,摘自百度 模板函数在声明的时候, 其实并不存在,函数地址也就无从谈起了,而导出到动态链接库的函数都需要有地址,也就是说——函数模板不具备导出的基本条件。
函数模板在调用时后,有了具体的实现,这个时候才有了地址。 如果要导出,必须将参数类型列表具体化。也就是要显式实例化。
至于静态变量的初始化,应该在每个子类的cpp文件中初始化一次。因为模板静态变量在每个子类中是不同的,所以子类要初始化。