我花了大约20分钟试图找出为什么我的一些模板方法通过编译而不是链接.
事实证明我需要明确声明我的模板方法.
这是这样的事情:
class Test {
template<class Source> void Save(Source& obj);
};
Run Code Online (Sandbox Code Playgroud)
然后我会在某处使用它:
Test t;
ClassDerivedFromInterface obj;
t.Save(obj);
Run Code Online (Sandbox Code Playgroud)
它编译得很好,但没有链接.直到我补充:
template void Test::Save(ClassDerivedFromInterface);
Run Code Online (Sandbox Code Playgroud)
我想了解在哪种情况下需要明确的声明.
谢谢
简而言之,您需要让实例化模板的翻译单元可以看到模板函数的整个主体(定义).所以当你说t.Save(obj);,那个翻译单元应该可以访问定义Save.通常,您可以通过在头文件本身中包含函数模板的定义来实现此目的.
这样做的原因是模板不是可以编译的普通代码,以后可以随意链接.相反,模板是一种代码生成工具,可以按需生成必要的代码 - 如果愿意,可以自动复制/粘贴,然后搜索和替换.
因此,在Save(ClassDerivedFromInterface&)您编写该行之前,函数的实际可编译代码不会存在.如果只有函数模板的声明是可见的,那么模板只生成具体函数的声明,但不生成它的正文,因此在链接时你会注意到函数丢失了.
回顾一下,模板本身无法编译,只有它们的具体实例可以,并且您必须注意确保在实例化时具体实例始终可用.显式实例化,因为它有效并允许您将一些特定实例打包到一个单独的TU中,但通常难以维护且不可伸缩,并且当您让编译器隐式实例化时,您可以避免显式实例化的其他缺点.因此,通常最好将整个定义打包到头文件中.
| 归档时间: |
|
| 查看次数: |
363 次 |
| 最近记录: |