C++踩坑-模板类

转自https://blog.csdn.net/u010585135/article/details/41829499

关于template<>只能定义在.h文件中:

 

在学习数据结构C++实现的时候,踩中了C++的一个坑,如下:

/**/
template 
class Search{

public:
	void search(st t, k num)//模板类函数只能定义于此
	{
		tar = t;
		key = num;
	}
	int Bisearch()
	{
		int low = 1;
		int high = tar.length;
		int mid;
		while (low < high)
		{
			mid = (low + high) / 2;
			if (tar.elem[mid] == key)
				return mid;
			else if (tar.elem[mid] < key)
				low = mid;
			else
				high = mid;
		}
		return -1;
	}
private:
	st tar;
	k key;
};

模板类Search的成员函数只能定义在.h文件中,无法在.cpp文件中定义,定义则会报错:

error LNK2019: 无法解析的外部符号 "public: int __thiscall Search::Bisearch(void)" (?Bisearch@?$Search@USSTable@@H@@QAEHXZ),该符号在函数 _main 中被引用

这个问题是关于模版类的成员函数的定义方法的问题。我按照普通类的写法,在function.h中声明类的成员函数,在function.cpp中写该函数的定义,然后在main.cpp中include文件,编译时把main.cpp和function.cpp放在同一个编译单元里面。按理这样就能生成可执行文件了,但是链接时却报以上错误。

原因是模版类在编译时是在使用的地方才实例化,但不同的.cpp文件是在link时才相互关联,因此编译main.cpp时只实例化了函数的声明,并且认为在某个地方已经实例化了函数的定义,悲剧的是编译function.cpp时并没有给main.cpp中的这个用法做实例化,于是linker就找不到main.cpp所需要的函数定义了。

于是只有两种解决办法,或者在function.cpp中给需要的实例化显示地做定义(这样做扩展性就很差),或者把template函数的定义也放在.h文件中。

转帖讨论了更加深入的解决方案,复制如下:

于是我和@吴磊达人讨论为什么C++没办法直接在编译时跨文件实例化template,结论是源于C的单文件编译单元的效率考虑,使得编译时(链接之前)是没办法知道其他编译单元到底需要什么实例。如果linker能给compiler反馈机制,使得linker之后还能再编译一遍给做必要的实例化,应该能提供这个特性(填上这个反直觉的坑)了,或者在编译之前专门做一遍预编译,给每个使用的template跨文件标记出需要的实例化,从而编译时就能解决这个问题了。

你可能感兴趣的:(C++)