c++ - 显式模板实例化如何影响链接器可以找到的内容?

标签 c++ templates

请看下面的代码,解开我的疑惑。

  1. ABC是一个模板,为什么我们把ABC类的成员函数定义放在test.cpp中却不报错?

  2. 如果我将 test.cpp 代码放入 test.h 并删除 2,那么它可以正常工作。为什么?

.

// test.h 
template <typename T> 
class ABC { 
public: 
   void foo( T& ); 
   void bar( T& ); 
}; 
// test.cpp 
template <typename T> 
void ABC<T>::foo( T& ) {} // definition 
template <typename T> 
void ABC<T>::bar( T& ) {} // definition 

template void ABC<char>::foo( char & );  // 1 
template class ABC<char>;                // 2 
// main.cpp 
#include "test.h" 
int main() { 
   ABC<char> a; 
   a.foo();     // valid with 1 or 2 
   a.bar();     // link error if only 1, valid with 2 
} 

最佳答案

在这两种情况下,您都在进行显式实例化。在第二种情况下,只有 ABC<char>::foo正在被实例化,而在第一种情况下 ABC<char>::bar也正在被实例化。

另一个类似的例子可能会阐明其含义:

// test.h
template <typename T>
class ABC {
public:
   void foo( T& );
   void bar( T& );
};
// test.cpp
template <typename T>
void ABC<T>::foo( T& ) {} // definition
template <typename T>
void ABC<T>::bar( T& ) {} // definition

template void ABC<char>::foo( char & );  // 1
template class ABC<char>;                // 2
// main.cpp
#include "test.h"
int main() {
   ABC<char> a;
   a.foo();     // valid with 1 or 2
   a.bar();     // link error if only 1, valid with 2
}

在例子中,在main编译器看不到 foo也不bar定义,所以它不能实例化方法。编译器在处理 main.cpp 时会很高兴地接受 main 中的代码,因为你告诉它 ABC是一个模板,它具有这两个功能,并假设它们将在其他翻译单元中定义。

在包含 test.cpp 的翻译单元中,编译器会看到两个方法定义,并且可以完全处理两个实例化(方法/类)。如果只有方法实例化 ([1]) 存在,编译器将只生成该方法,并留下 bar不明确的。因此,任何包含 test.h 的代码都会链接到已编译的 test.cpp 并仅使用 foo方法将编译和链接,但使用 bar由于未定义,将无法链接。

显式实例化类模板会为所有成员方法生成符号,在这种情况下,任何包含 test.h 和针对已编译 test.cpp 目标文件的链接的翻译单元都将进行编译和链接。

关于c++ - 显式模板实例化如何影响链接器可以找到的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2735417/

相关文章:

c++ - 读句柄错误

templates - Photoshop模板

c++ - Clang 解析公共(public)枚举类

c++ - 如何基于 basic_streambuf 构建 filtered_streambuf?

C++ 无法将 'type' 转换为 'type*'

php - mustache php gettext()

c++ - C++11 中递归元函数的延迟返回类型解析

c++ - 如何在 OSX 上更新 g++ 编译器

c++ - 合格的 friend 功能模板实例化

c++ - 模板参数推导 - 推导 T 并使用 T&&