C++ 模板类友元之输出流操作符重载
几个关键点:
需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行!
友元函数的函数名后面的<>,必须要有。
#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++ 模板类友元之输出流操作符重载的更多相关文章
- 15.C++-操作符重载、并实现复数类
首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...
- C++中的链表节点用模板类和用普通类来实现的区别
C++中的链表节点通常情况下类型都是一致的.因此我们可以用模板来实现. #include <iostream> using namespace std; template<typen ...
- C++中的操作符重载
一.什么是操作符重载 操作符重载可以分为两部分:“操作符”和“重载”.说到重载想必都不陌生了吧,这是一种编译时多态,重载实际上可以分为函数重载和操作符重载.运算符重载和函数重载的不同之处在于操作符重载 ...
- 15.C++-操作符重载
首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...
- C++解析(17):操作符重载
0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...
- c++之旅:操作符重载
操作符重载 操作符重载可以为操作符添加更多的含义,操作符重载的作用的对象是类 那些操作符可以重载 除了下面几个操作符不能重载外,其它的操作符都能重载 . :: .* ?: sizeof 操作符重载的本 ...
- 操作符重载(day07)
二十 操作符重载 eg:复数x+yi +4i (+2i) + (+4i) = +6i 双目操作符(L # R) 1.1 运算类的双目操作符:+ - * / -->左右操作数可以是左值也可以是右值 ...
- C++中操作符重载的概念
1,下面的复数解决方案是否可行? 1,代码示例: class Comples { public: int a; int b; }; int main() { Complex c1 = {, }; Co ...
- C#中如何利用操作符重载和转换操作符
操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...
随机推荐
- Python splitlines()方法
描述 Python splitlines() 按照行界符('\r', '\r\n', \n'等)分隔,返回一个包含各行作为元素的列表,默认不包含行界符. 能被识别的行界符: 行界符 描述 \n Lin ...
- -174dBm的含义
常温下(290K)一个热电阻会产生少量的噪声能量P=kTB k = 玻尔兹曼常数(1.38 x 10–23 J/K)T = 温度(K)B = 噪声带宽(Hz) 由于总噪声功率是测量带宽的函数,数值通常 ...
- jenkins 发送邮件失败
jenkins 配置发送邮件,发送测试邮件,邮件发送失败: Failed to send out e-mail javax.mail.MessagingException: Could not con ...
- How to install Mysql in the CentOS
This article will walk through you the process of installing and updating latest MySQL 5.7.9 version ...
- git的全局变量
git的全局变量可以用在命令行设置: git config --global user.name "litifeng" git config --global user.email ...
- [k8s]kubeadm k8s免费实验平台labs.play-with-k8s.com,k8s在线测试
k8s实验 labs.play-with-k8s.com特色 这玩意允许你用github或dockerhub去登录 这玩意登录后倒计时,给你4h实践 这玩意用kubeadm来部署(让你用weave网络 ...
- javascript原生bind方法ie低版本兼容详解
上一篇文章讲到了javascript原生的bind方法: http://www.cnblogs.com/liulangmao/p/3451669.html 这篇文章就在理解了原生bind方法的原理以后 ...
- Java、MySQL - 前补0的方法
前补0的格式化方式在业务系统中经常使用,记录下此api. Java: public static void main(String[] args) { // 0002 System.out.print ...
- Linux模块的加载和卸载
Linux操作系统中模块操作相关命令解释lsmod 查看已经安装好的模块, 也可以查看/proc/modules文件的内容. 实际上,lsmod读命令就是通过查看/proc/modules的内容来显 ...
- wpf treeview中的两个事件
使用模板HierarchicalDataTemplate <HierarchicalDataTemplate x:Key="BookMarkTemplate" > &l ...