C++类模板声明与实现分离

时间:2021-08-10 23:17:18

当模板声明与实现分离未处理得当时,会出现链接错误,如下:

error LNK2019: unresolved external symbol poisson referenced

其实,LNK2019错误一般都是 compile是能找到相应的header (.h)文件,但链接时找不到相应的 lib 库文件(也含dll文件)。

首先,对编译器来说模板的声明与实现并不能真正的分离,我们要达到的目的是形式化地将模板声明与实现分别在两个文件中编写

方法如下:

方法一、当抽象体较为简单时,最好将声明与实现放在一起!

方法二、在头文件中编写模板声明,在源文件中编写模板实现,并在头文件的模板声明后包含该对应的源文件(建议使用.inl)!注意,该源文件中只能用些编写该模板的实现内容,不要有其他无关的源码实现。

/// \brief 2-D Matrix class.
template< class T >
class Matrix
{
//friend class Array<T>;
friend class Vector<T>;
friend class SubMatrix<T>;
public:
Matrix();
Matrix(const int rows, const int columns);
Matrix(const int rows, const int columns, T init);
Matrix(string str);
Matrix(Matrix<T> &m); // copy constructor
~Matrix();
void Clean();
...
};
#include "Matrix.inl"// Matrix.inl文件中是模板实现

inl文件介绍
inl文件是内联函数的源文件。内联函数通常在C++头文件中实现,但是当C++头文件中内联函数过多的情况下,我们想使头文件看起来简洁点,能不能像普通函数那样将内联函数声明和函数定义放在头文件和实现文件中呢?当然答案是肯定的,具体做法将是:将内联函数的具体实现放在inl文件中,然后在该头文件末尾使用#include引入该inl文件。
由于编译器等不支持将模板函数、模板类等放单独分开编译,但是有了inl文件,我们可以把声明放在头文件中,然后将具体实现放在inl文件中。
对于比较大的工程来说,出于管理方面的考虑,模板函数、模板类的声明一般放在一个或少数几个头文件中,然后将其定义部分放在inl文件中。这样可以让工程结构清晰、明了。

方法三、当模板声明与实现分离时,在源文件中显式声明要使用的模板实例类型(不推荐)
template class TestTemplate<int>;
template class TestTemplate<float>;

Tips:关于书写类模板成员函数的格式

“类模板的成员函数是一个普通函数。但是类模板的每个实例都有其自己版本的成员函数。因此类模板的成员函数具有和模板相同的模板参数。因此定义在类模板之外的成员函数就必须以关键字 template 开始,后接类模板参数列表。”——《C++ Primer》中文版,第五版,P585

template <typename T> // 分离编写时必不可少的
void ClassA<T>::func(){
std::cout << "TestTemplate "<< std::endl;
}