zoukankan      html  css  js  c++  java
  • C++ 模板类友元之输出流操作符重载

    几个关键点:

      需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行!

      友元函数的函数名后面的<>,必须要有。

     1 #include <stdio.h>
     2 #include <iostream>
     3 using namespace std;
     4 
     5 //前置声明,你妹啊
     6 template<class T> class A;
     7 template<class T> ostream &operator<< (ostream &out, const A<T> &_a);
     8 template<class T1, class T2> class B;
     9 template<class T1, class T2> ostream &operator<< (ostream &out, const B<T1, T2> &_b);
    10 
    11 template<class T> class A
    12 {
    13 public:
    14     A(){}
    15     A(T _a, T _b):a(_a),b(_b){}
    16     ~A(){}
    17 private:
    18     T a;
    19     T b;
    20 
    21     friend ostream &operator<< <> (ostream &out, const A<T> &a);
    22 };
    23 
    24 template<class T> ostream &operator<< (ostream &out, const A<T> &_a){
    25     out<<_a.a<<"--"<<_a.b;
    26     return out;
    27 }
    28 
    29 template<class T1, class T2> class B: public A<T1>
    30 {
    31 public:
    32     B(){}
    33     B(T1 _a, T1 _b, T2 _c):A<T1>(_a,_b),c(_c){} //A<T1>
    34     ~B(){}
    35 private:    
    36     T2 c;
    37 
    38     friend ostream &operator<< <>(ostream &out, const B<T1, T2> &_b);
    39 };
    40 template<class T1, class T2> ostream &operator<< (ostream &out, const B<T1, T2> &_b){
    41     // out<<(A<T1>)_b;
    42     // out<<"--"<<_b.c;
    43 
    44     out<<(A<T1>)_b<<"--"<<_b.c;
    45     return out;
    46 }
    47 
    48 int main(int argc, char const *argv[])
    49 {
    50     A<int> x(1, 3);
    51     B<char, int> y('a', 'b', 5);
    52 
    53     cout<< x <<endl;
    54     cout<< y <<endl;
    55 
    56     return 0;
    57 }
    View Code

    以上认识太片面,请忽略。

    这里 有完美的解释!

    大意如下:

    模板类的友元其实有多个可能,关键在于这个友元是该模板类的一个/特定具现(实例)的友元,还是所有具现(实例)的友元。

    注意1,这里不需要考虑与泛型无关的友元--例如输出一句话之类的,完全没有意义。

    注意2,这里的多个可能是编译之前的可能,编译之后还是一个具现(实例)有一个友元(---猜测)。

    总之,我认为,这两种仅仅是出发点不同,但最终目的地一致。

    一、友元是模板类的一个/特定具现(实例)的友元,需要前置声明

    #include <stdio.h>
    #include <iostream>
    using namespace std;
    
    //前置声明,你妹啊
    template<class T> class A;
    template<class T> ostream &operator<< (ostream &out, const A<T> &_a);
    template<class T1, class T2> class B;
    template<class T1, class T2> ostream &operator<< (ostream &out, const B<T1, T2> &_b);
    
    template<class T> class A
    {
    public:
        A(){}
        A(T _a, T _b):a(_a),b(_b){}
        ~A(){}
    private:
        T a;
        T b;
    
        friend ostream &operator<< <> (ostream &out, const A<T> &a);
    };
    
    template<class T> ostream &operator<< (ostream &out, const A<T> &_a){
        out<<_a.a<<"--"<<_a.b;
        return out;
    }
    
    int main(int argc, char const *argv[])
    {
        A<int> x(1, 3);
        cout<< x <<endl;
    
        return 0;
    }

    二、友元是所有具现(实例)的友元,不需要前置声明:

    #include <iostream>
    
    using namespace std;
    
    //友元operator<< 是模板类A的所有实例的友元(实际上还是多个operator<<)--不需要前置声明。
    template <typename T>
    struct A {
        T a;
        A(T _a) :a(_a) {}
    
        template <typename T1> friend ostream &operator<< (ostream &out, const A<T1> &_a);//这里的T1?? 由于<<输出的是A的实例的对象,所以实际上这里的T1编译之后还是T--因为编译器找不到其他可能。
    };
    
    template <typename T>
    ostream & operator<< (ostream & out, const A<T> &_a) {
        out << _a.a;
        return out;
    }
    
    int main() {
        A<int> x(15);
        cout << x << endl;
    
    
        return 0;
    }
  • 相关阅读:
    BZOJ 4316: 小C的独立集 (仙人掌,树形DP)
    LOJ #2587. 「APIO2018」铁人两项 (圆方树,树形DP)
    BZOJ 5329: [Sdoi2018]战略游戏 (圆方树,树链的并)
    CF487E Tourists (圆方树,LCT)
    BZOJ 4873: [Shoi2017]寿司餐厅 最大权闭合图
    【转】python文件打开方式详解——a、a+、r+、w+区别
    【转】使用git将项目上传到github(最简单方法)
    整数型数组组合成字符串
    【转】浏览器中输入url后发生了什么
    去除列表中重复的元素
  • 原文地址:https://www.cnblogs.com/larryzeal/p/5664418.html
Copyright © 2011-2022 走看看