chr*_*tte 5 c++ inheritance templates static-members
目前我正在开发一个C++项目,我打算在其中嵌入Lua脚本.因此,某些类需要导出到Lua,我想让它更方便,因此我创建了一个模板类:
template <class T>
class ExportToLua {
public:
ExportToLua() {}
~ExportToLua() {}
private:
static int m_registered;
};
template <class T> int ExportToLua<T>::m_registered = T::exportToLua();
Run Code Online (Sandbox Code Playgroud)
现在每一个需要导出类源自ExportToLua<T>
与T
="之类要导出".例:
class Example: public ExportToLua<Example> {
public:
Example();
virtual ~Example();
static int exportToLua();
private:
};
Run Code Online (Sandbox Code Playgroud)
Example
静态成员函数在哪里exportToLua()
保存特定于类的注册码.我的理解是ExportToLua<T>::m_registered
每个编译单元都存在一个静态成员变量的实例- 即每个编译单元T
.
但是当我启动我的程序时,注册码永远不会被调用.例如在example.cpp中:
int Example::exportToLua() {
std::cout << "int Example::exportToLua()" << std::endl;
return -2;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行程序时,我从未看到此消息.
知道为什么吗?编译器是否"优化了"静态变量m_registered
,因为我没有在任何地方使用它?
感谢您的输入,
最好的,克里斯托弗
您已经在标准中找到了行为如此的原因。因此,作为解决方法,您可以通过从模板构造函数或析构函数引用该静态成员来“欺骗”编译器实例化该静态成员。
#define FORCE_INSTANTIATE(x) (x)
// or (avoids -Wall and -pedantic warnings)
// template <typename T> inline void FORCE_INSTANTIATE(T) {}
template <class T>
class ExportToLua
{
public:
ExportToLua() {}
virtual ~ExportToLua() { FORCE_INSTANTIATE(m_registered); }
private:
static int m_registered;
};
Run Code Online (Sandbox Code Playgroud)
它似乎在这个演示中起作用。
编辑:正如 DyP 正确指出的那样,单一定义规则在这里发挥作用,决定是否ExportToLua<T>::m_registered
实例化。
为了保证隐式实例化,请确保至少满足以下条件之一:
如果出于某种原因无法满足这些条件,那么您需要从模板中显式实例化所需的成员。例如,
class Example: public ExportToLua<Example>
{
public:
// ...
static int exportToLua();
// etc.
};
template int ExportToLua<Example>::m_registered;
Run Code Online (Sandbox Code Playgroud)
如果需要,您可以将其包装到宏中,以便更好地使用。