几个关键点:

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

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

 #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;
} template<class T1, class T2> class B: public A<T1>
{
public:
B(){}
B(T1 _a, T1 _b, T2 _c):A<T1>(_a,_b),c(_c){} //A<T1>
~B(){}
private:
T2 c; friend ostream &operator<< <>(ostream &out, const B<T1, T2> &_b);
};
template<class T1, class T2> ostream &operator<< (ostream &out, const B<T1, T2> &_b){
// out<<(A<T1>)_b;
// out<<"--"<<_b.c; out<<(A<T1>)_b<<"--"<<_b.c;
return out;
} int main(int argc, char const *argv[])
{
A<int> x(, );
B<char, int> y('a', 'b', ); cout<< x <<endl;
cout<< y <<endl; return ;
}

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

这里 有完美的解释!

大意如下:

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

注意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(, );
cout<< x <<endl; return ;
}

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

#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();
cout << x << endl; return ;
}

C++ 模板类友元之输出流操作符重载的更多相关文章

  1. 15.C++-操作符重载、并实现复数类

    首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...

  2. C++中的链表节点用模板类和用普通类来实现的区别

    C++中的链表节点通常情况下类型都是一致的.因此我们可以用模板来实现. #include <iostream> using namespace std; template<typen ...

  3. C++中的操作符重载

    一.什么是操作符重载 操作符重载可以分为两部分:“操作符”和“重载”.说到重载想必都不陌生了吧,这是一种编译时多态,重载实际上可以分为函数重载和操作符重载.运算符重载和函数重载的不同之处在于操作符重载 ...

  4. 15.C++-操作符重载

    首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...

  5. C++解析(17):操作符重载

    0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...

  6. c++之旅:操作符重载

    操作符重载 操作符重载可以为操作符添加更多的含义,操作符重载的作用的对象是类 那些操作符可以重载 除了下面几个操作符不能重载外,其它的操作符都能重载 . :: .* ?: sizeof 操作符重载的本 ...

  7. 操作符重载(day07)

    二十 操作符重载 eg:复数x+yi +4i (+2i) + (+4i) = +6i 双目操作符(L # R) 1.1 运算类的双目操作符:+ - * / -->左右操作数可以是左值也可以是右值 ...

  8. C++中操作符重载的概念

    1,下面的复数解决方案是否可行? 1,代码示例: class Comples { public: int a; int b; }; int main() { Complex c1 = {, }; Co ...

  9. C#中如何利用操作符重载和转换操作符

    操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...

随机推荐

  1. 安装ubuntu和windows双系统后,如何修改默认启动项

    在安装了Ubuntu16.04系统之后,系统会默认自启动Ubuntu16.04,而我们大多数情况下可能都在使用windows系统,不修改默认设置,不经意间便会启动了Ubuntu16.04,通过我的经历 ...

  2. mysql如何查找某字段所在表

    如果是5.0以上的,以root用户连接,可以看到一个叫information_schema的表, 然后只要:use information_schema; select `TABLE_NAME`fro ...

  3. Vuejs2.0 + bootstrap demo

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. angular.js 中同步视图和模型数据双向绑定,$watch $digest $apply 机制

    Angular.js 中的特性,双向绑定. 让视图的改变直接反应到数据中,数据的改变又实时的通知到视图,如何做到的? 这要归功于 scope 下面3个重要的方法: $watch $digest $ap ...

  5. Artificial-Intelligence BOOKs与算法

    http://mindhacks.cn/2008/09/11/machine-learning-and-ai-resources/ https://www.amazon.com/Information ...

  6. cocos2d-x Vector 使用心得

    标准库Vector类型使用需要的头文件:#include <vector>Vector:Vector 是一个类模板.不是一种数据类型. Vector<int>是一种数据类型. ...

  7. go--Ubuntu下安装GO LANG,测试输入hello world

    1.下载go语言源码,https://storage.googleapis.com/golang/go1.6.1.linux-amd64.tar.gz 2.解压缩源码包tar zxvf go1.6.1 ...

  8. ng-bind和{{}}插值法

    引言 今天调bug的时候遇到了一个问题,就是有的时候加载出来的数据没有数据的时候出现的是{{TeacherName}},一看这个不是我在页面上绑的值吗?怎么这样就显示出来了呢…… 针对这个问题,想起来 ...

  9. servlet的编码原理

    编码问题: 在介绍编码问题前,先介绍一下java平台(JVM)上的编码转化情况.首先要说明的一点,在JVM中,即java平台上,运行的程序一定都是Unicode编码方式的.对于代码中的字符串常量,根据 ...

  10. JDK Logger 简介 (zhuan)

    http://antlove.iteye.com/blog/1924832 ******************************************* 一 简述 java.util.log ...