类模板里面的函数写在类模板里面和写在类模板的外面,且在1个.cpp文件中
和类一样,类模板里面声明的函数,其函数体写在类里面和外面都行,但是有一点需要注意:1.用友元函数重载<< 或 >>运算符,函数声明写在类模板里面,函数实现写在类模板外面,要在函数名和函数输入参数之间写上Typename定义的那个类型,如template <typename T>,则应写上<T>。举个例子,如果重载运算符<<,且重载函数的函数体写在类模板的外面,则在类模板里面声明重载函数时,函数声明应该写成ostream operator<< <T> (ostream&,类模板名<T>&)。
上面这个知识点是很多新手易犯的错误,很多人在网上跪求原因,一定要注意!
2.一般性的友元函数,函数声明写在类模板里面,函数实现写在类模板外面,需要在类的前面添加函数的前置声明,否则编译肯定通不过。因为这个方法比较复杂,所以碰到类模板的时候,能不用友元函数尽量不要用友元函数。
在类的前面添加前置函数声明的方法如下:
1)template <Typename T>
class Complex //这里假定类模板的名字就是Complex,这句话是类的前置声明
template <Typename T>
Complex<T> myfun(class<T>& ,class<T>&) //函数的前置声明
2)在类模板的内部声明应写成:friend Complex myfun<T>(Complex& ,Complex&) ,这里必须要加<T>
3)友元函数在类模板外面的实现写成:
Complex<T> myfun(class<T>& c1 ,class<T>& c2)
{...}
4)友元函数的调用写成:myfun<int>(c1,c2),这里<int>也是必须要加的
究其原因,与C++编译器对类模板的二次编译有关。当C++编译器遇到类模板里面的函数声明时,生成一个函数头;遇到类模板外面的函数体实现时,又生成了一个函数头。因为友元函数是全局函数,它不属于类模板,所以两次生成的函数头不一样,导致了C++编译器找不到由原函数的函数体实现了,所以编译就会报错。而且不同的编译器,可能有的支持这个语法,有的不支持这个语法,所以碰到函数模板时一定要谨慎使用友元函数,能不用就不要用。
下面是具体实例:
1 #include <iostream> 2 3 using namespace std; 4 5 /* 6 //1.类模板的函数都写在类的内部 7 template <typename T> 8 class Complex 9 { 10 friend ostream& operator<<(ostream& out,Complex& c) 11 { 12 out<<c.a<<"+"<<c.b<<"i"; 13 return out; 14 } 15 16 public: 17 Complex(T a,T b) 18 { 19 this->a=a; 20 this->b=b; 21 } 22 23 Complex operator+(Complex& c) 24 { 25 Complex temp(this->a+c.a,this->b+c.b); 26 return temp; 27 } 28 29 void printCom() 30 { 31 cout<<this->a<<"+"<<this->b<<"i"<<endl; 32 } 33 34 private: 35 T a; 36 T b; 37 }; 38 */ 39 40 //2.类模板的函数都写在类的外部 41 template <typename T> 42 class Complex 43 { 44 //注意,友元函数在类模板的类体里面声明的时候,在函数的名字和函数参数类型之间加了一个<T>,若不加这个<T>,则编译通不过! 45 friend ostream& operator<<<T>(ostream& out,Complex& c); 46 47 public: 48 Complex(T,T);//构造函数 49 Complex operator+(Complex& );//重载“+”操作符 50 void printCom();//普通函数 51 52 private: 53 T a; 54 T b; 55 }; 56 57 //注意友元函数在类体里面的声明的写法! 58 template <typename T> 59 ostream& operator<<(ostream& out,Complex<T>& c) 60 { 61 out<<c.a<<"+"<<c.b<<"i"; 62 return out; 63 } 64 65 template <typename T> 66 Complex<T>::Complex(T a,T b) 67 { 68 this->a=a; 69 this->b=b; 70 } 71 72 template <typename T> 73 Complex<T> Complex<T>::operator+(Complex<T>& c) 74 { 75 Complex<T> temp(this->a+c.a,this->b+c.b); 76 return temp; 77 } 78 79 template <typename T> 80 void Complex<T>::printCom() 81 { 82 cout<<this->a<<"+"<<this->b<<"i"<<endl; 83 } 84 85 int main() 86 { 87 Complex<float> c1(1.2,2.5),c2(3.2,5.3); 88 89 c1.printCom(); 90 c2.printCom(); 91 92 cout<<c1+c2<<endl; 93 94 return 0; 95 }