类模板里面的函数写在类模板里面和写在类模板的外面,且在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 }
原文地址:https://www.cnblogs.com/jswu-ustc/p/8514434.html