C++ 模板类友元之输出流操作符重载

时间:2021-12-02 17:50:53

几个关键点:

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

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

C++ 模板类友元之输出流操作符重载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;
}