一般来说,如果将声明类模板的.h文件、实现类模板函数的.cpp文件、以及主函数所在的.cpp文件写在3个文件里,则主函数所在的.cpp问价需要包含类模板实现的.cpp文件,而不能像普通的函数那样包含.h文件。这时因为C++对类模板的编译是二次编译,主函数所在.cpp只包含类模板的.h文件的话,主函数体里面是无法找到类模板的函数体实现的。
例如:
//1.mytest.h文件 #ifndef MYTEST_H #define MYTEST_H #include <iostream> using namespace std; template <typename T> class Complex { //注意,友元函数在类模板的类体里面声明的时候,在函数的名字和函数参数类型之间加了一个<T>,若不加这个<T>,则编译通不过! friend ostream& operator<<<T>(ostream& out,Complex& c); public: Complex(T,T);//构造函数 Complex operator+(Complex& );//重载“+”操作符 Complex operator-(Complex& );//重载“-”操作符 void printCom();//普通函数 private: T a; T b; }; #endif //2.mytest.cpp文件 #include <iostream> #include "mytest.h" using namespace std; //注意友元函数在类体里面的声明的写法! template <typename T> ostream& operator<<(ostream& out,Complex<T>& c) { out<<c.a<<"+"<<c.b<<"i"; return out; } template <typename T> Complex<T>::Complex(T a,T b) { this->a=a; this->b=b; } template <typename T> Complex<T> Complex<T>::operator+(Complex<T>& c) { Complex<T> temp(this->a+c.a,this->b+c.b); return temp; } template <typename T> Complex<T> Complex<T>::operator-(Complex<T>& c) { Complex<T> temp(this->a-c.a,this->b-c.b); return temp; } template <typename T> void Complex<T>::printCom() { cout<<this->a<<"+"<<this->b<<"i"<<endl; } //3.main.cpp文件 #include <iostream> #include "mytest.cpp" using namespace std; int main() { Complex<float> c1(1.2,2.5),c2(3.2,5.3); cout<<c1+c2<<endl; return 0; }
一般来说,都会把类模板的声明和实现放在一个.h文件里面,然后直接扔给别人一个.h文件,这样一般不会出现编译错误。