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类型的实例使用+操作符的时候,编译器会生成 ...
随机推荐
- unity3d 通过添加rigidBody来指明物体是动态的,以避免cache开销
unity3d 通过添加rigidBody来指明物体是动态的,以避免cache开销. 如果不添加rigidBody,则unity会认为它是静态的,会对物理计算进行cache,但如果此物体实际上tran ...
- GPS轨迹数据集免费下载资源整理
https://blog.csdn.net/liangyihuai/article/details/58335510
- js实现页面时间动态变化
利用函数嵌套和setTimeout函数实现时间动态变化 var myDate = new Date(); myDate.getYear(); //获取当前年份(2位) myDate.getFullYe ...
- 聊天server-解密陌生人(10)位置管理和获取周围一公里陌生人
提示: 由于project略微有点大对我个人来说.所以可能在某些方面讲的不清楚或逻辑性不够强,假设有问题请@我. 原project:https://github.com/LineChen/ 六.用户位 ...
- Ubuntu和centos下查看包的安装路径
安装包后,如何查看安装的具体路径? Ubuntu下: dpkg -L <包名> CentOS下: rpm -ql <包名> 助记: l为list的首字母. q为query ...
- jQuery判断复选框是否勾选
一个功能复选框勾选时给input表单赋值,复选框取消时将表单值清除. 功能:复选框勾选时给input表单赋值,复选框取消时将表单值清除. 实现源码:cyfID为复选框的id $("#cyfI ...
- cocos2d-x--精灵反转效果--CCOrbitCamera
CCSprite* pSprite = CCSprite::spriteWithFile("grossini.png"); pSprite->setPosition(ccp( ...
- 黑客编程教程(十五)HTTP代理
#include <stdio.h> #include <winsock2.h> #define MAXBUFLEN 20480 #define HTTPADDLEN 50 # ...
- SQL Developer 警告--无法安装某些模块
第一次启动正常,第二次启动就开始报错,说无法安装某写模块.具体如下: 警告--无法安装某些模块(Warning - could not install some modules) 在oracle官方的 ...
- 每日英语:Mercedes Sheds Its 'Old' Design
Daimler AG's flagship Mercedes-Benz often gets the rap for being an 'old man's car.' More unusual is ...