zoukankan      html  css  js  c++  java
  • 类模板里面的函数写在类模板里面和写在类模板的外面,且在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 }
  • 相关阅读:
    面向对象
    Vue + webpack 项目实践
    配置webstorm监听less时时转换
    delegate事件代理
    JS for 循环
    JS while 循环
    JS switch 分支语句
    JS if 判断
    JS 运算符
    JS typeof() parseInt() parseFloat()
  • 原文地址:https://www.cnblogs.com/jswu-ustc/p/8514434.html
Copyright © 2011-2022 走看看