模板实例化
我一直在寻找一些可以写一篇小文章的东西
这似乎是个不错的选择。
论坛上有很多关于这个问题的帖子,作者将
模板拆分为 *.h 文件和 *.cpp 文件,并遇到链接器
问题。
通常给出的答案是将所有模板内容放入 *.h 文件中
因为必须这样做。
类/函数。
这并不完全正确。
C++ 有隐式模板实例化和显式实例化
隐式实例化
在
template.h 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
class myTemplate
{
private:
T data;
public:
myTemplate();
myTemplate(T t);
T getData() const;
void displayData() const;
static int someValue;
};
template<typename T>
myTemplate<T>::myTemplate()
:data()
{
}
template<typename T>
myTemplate<T>::myTemplate(T t)
:data(t)
{
}
template <typename T>
T myTemplate<T>::getData() const
{
return data;
}
template <typename T>
void myTemplate<T>::displayData() const
{
std::cout << data <<std::endl;
}
template<typename T>
int myTemplate<T>::someValue = 100;
#endif
|
在 main.cpp 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include <iostream>
#include "template.h"
using namespace std;
int main()
{
myTemplate<int> myTi(5);
myTi.displayData();
myTemplate<float> myTf(3.5f);
myTf.displayData();
return 0;
}
|
在上面的示例中,完整的模板定义位于头文件中
main.cpp 包含该头文件 - 因此在编译
和链接过程中不会出现问题。
如果我们忘记定义
displayData() 函数
那么我们会收到链接器错误,而不是编译器错误。
//=========================================================================================//
显式实例化 假设我们要将模板类拆分为头文件和源文件。
所以我们有 main.cpp 和 template.cpp。
我们编译这两个文件,但会收到链接器错误,因为 template.cpp
文件中的实际代码未被实例化。
要使编译器实例化所需的代码,我们可以使用显式实例化。
template.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
class myTemplate
{
private:
T data;
public:
myTemplate();
myTemplate(T t);
T getData() const;
void displayData() const;
static int someValue;
};
#endif
|
template.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
#include "template.h"
#include <iostream>
//template functions
template<typename T>
myTemplate<T>::myTemplate()
:data()
{
}
template<typename T>
myTemplate<T>::myTemplate(T t)
:data(t)
{
}
template <typename T>
T myTemplate<T>::getData() const
{
return data;
}
template <typename T>
void myTemplate<T>::displayData() const
{
std::cout << data <<std::endl;
}
template<typename T>
int myTemplate<T>::someValue = 100;
//The explicit instantiation part
template class myTemplate<int>;
template class myTemplate<float>;
|
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
#include <iostream>
#include "template.h"
using namespace std;
int main()
{
myTemplate<int> myTi(5);
myTi.displayData();
myTemplate<float> myTf(3.5f);
myTf.displayData();
return 0;
}
|
重要的部分是
template.cpp 中的最后几行。我们知道我们需要一个
myTemplate<int> 和一个
myTemplate<float>,因此我们显式地要求编译器为这些
两种类类型的所有的可实例化部分生成代码。
请注意实例化指令的编写方式。
我们现在可以成功地编译和链接我们的代码。
我们还可以显式地实例化模板函数,或单个模板类成员函数。