• 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;
    }
  • 相关阅读:
    bzoj4950
    P1377发奖金
    环信SDK与Apple Watch的结合(1)
    环信SDK与Apple Watch的结合(2)
    【Objective-C】0-第一个OC的类
    【Objective-C】4-空指针和野指针
    【Objective-C】3 -self关键字
    【Objective-C】2.自定义构造方法和description方法
    Swift函数|闭包
    Swift枚举|结构体|类|属性|方法|下标脚本|继承
  • 原文地址:https://www.cnblogs.com/larryzeal/p/5664418.html
Copyright © 2020-2023  润新知