C++学习笔记55——类模板的输入输出操作符
来源:互联网 发布:计算机专业与大数据 编辑:程序博客网 时间:2024/06/10 19:37
根据重载操作符那一章的规定,输入输出操作符必须作为友元而不是类的成员函数重载。
在类的模板中重载输入输出操作符的方式主要有两种:
- 在类模板中做friend声明,在模板外做函数定义;
- 在类模板中定义友元操作符;
1,在类外定义友元操作符
1.1 将函数模板设为友元
#include <iostream>#include <bitset>using namespace std;template<int h, int w> class MyScreen{public:MyScreen() :contents(h*w, '#'), width(w), height(h) {}MyScreen(string new_contents) :contents(new_contents), width(w), height(h) {}template<int h1, int w1> friend ostream& operator<< (ostream& os, const MyScreen<h1, w1>& ScreenOne);private:int width;int height;string contents;};template<int h2, int w2> ostream& operator <<(ostream &os, const MyScreen<h2, w2> &ScreenOne){os << "height:" << ScreenOne.height << "\n"<< "width:" << ScreenOne.width << "\n"<< "contents:" << ScreenOne.contents ;return os;}int main(){MyScreen<3, 4> ScreenOne("HuangYang Love WHY");cout << ScreenOne << endl;system("pause");return 0;}
执行结果:
1.2 将函数模板的一个实例设为友元
其他不变,将类模板的定义改为如下形式:
template<int h, int w> class MyScreen{public:MyScreen() :contents(h*w, '#'), width(w), height(h) {}MyScreen(string new_contents) :contents(new_contents), width(w), height(h) {}friend ostream& operator<< <h,w> (ostream& os, const MyScreen<h, w>& ScreenOne);private:int width;int height;string contents;};注意,做友元声明的时候,必须跟上模板形参。
因为这里将输出流操作符定义成了一个函数模板,设为友元的仅仅是这个模板的一个实例。
模板形参不可省略。如果将友元声明改成:
friend ostream& operator<< (ostream& os, const MyScreen<h, w>& ScreenOne);
则编译报错。
“fatal error LNK1120: 1 个无法解析的外部命令”
因为此时,在模板外定义重定义的输出流操作符与模板类声明的友元输出流操作符不是同一个操作符。
代码总结如下:
#include <iostream>#include <bitset>using namespace std;template<int h, int w> class MyScreen{public:MyScreen() :contents(h*w, '#'), width(w), height(h) {}MyScreen(string new_contents) :contents(new_contents), width(w), height(h) {}// 整个模板设为友元,OKtemplate<int h1, int w1> friend ostream& operator<< (ostream& os, const MyScreen<h1, w1>& ScreenOne);// 模板的一个实例设为友元,OK//friend ostream& operator<< <h,w> (ostream& os, const MyScreen<h, w>& ScreenOne);// Error!//friend ostream& operator<< (ostream& os, const MyScreen<h, w>& ScreenOne);// Errorprivate:int width;int height;string contents;};template<int h2, int w2> ostream& operator <<(ostream &os, const MyScreen<h2, w2> &ScreenOne){os << "height:" << ScreenOne.height << "\n"<< "width:" << ScreenOne.width << "\n"<< "contents:" << ScreenOne.contents ;return os;}int main(){MyScreen<3, 4> ScreenOne("HuangYang Love WHY");cout << ScreenOne << endl;system("pause");return 0;}
2,在类内定义友元操作符
template<int h, int w> class MyScreen{public:MyScreen() :contents(h*w, '#'), width(w), height(h) {}MyScreen(string new_contents) :contents(new_contents), width(w), height(h) {}//template<int h1, int w1> friend ostream& operator<< (ostream& os, const MyScreen<h1, w1>& ScreenOne)//OK//friend ostream& operator<< <h, w> (ostream& os, const MyScreen<h, w>& ScreenOne)//OKfriend ostream& operator<< (ostream& os, const MyScreen<h, w>& ScreenOne)//OK{os << "height:" << ScreenOne.height << "\n"<< "width:" << ScreenOne.width << "\n"<< "contents:" << ScreenOne.contents;return os;}private:int width;int height;string contents;};int main(){MyScreen<3, 4> ScreenOne("HuangYang Love WHY");cout << ScreenOne << endl;system("pause");return 0;}
当在类内部定义时,三种声明方式都可以。
3,多文件编译
以上的描述都是针对单文件编译的情况。但是,我们在日常中经常遇到的情况却是多文件编译。
一旦将输出流定义在另外一个文件中时,就会报错。
比如将1.1的例子分成3个文件friend.h、friend.cpp、main.cpp来实现:
friend.h:
#pragma once#include <iostream>#include <bitset>using namespace std;template<int h, int w> class MyScreen{public:MyScreen() :contents(h*w, '#'), width(w), height(h) {}MyScreen(string new_contents) :contents(new_contents), width(w), height(h) {}// 整个模板设为友元template<int h1, int w1> friend ostream& operator<< (ostream& os, const MyScreen<h1, w1>& ScreenOne);private:int width;int height;string contents;};
#include "friend.h"template<int h2, int w2> ostream& operator <<(ostream &os, const MyScreen<h2, w2> &ScreenOne){os << "height:" << ScreenOne.height << "\n"<< "width:" << ScreenOne.width << "\n"<< "contents:" << ScreenOne.contents;return os;}
main.cpp:
#include "friend.h"int main(){MyScreen<3, 4> ScreenOne("HuangYang Love WHY");cout << ScreenOne << endl;system("pause");return 0;}
则编译报错:
“fatal error LNK1120: 1 个无法解析的外部命令”
原因没想明白!!!
0 0
- C++学习笔记55——类模板的输入输出操作符
- C++学习笔记39——重载输入输出操作符
- c语言学习笔记(3)——输入输出
- C语言学习笔记——格式化输入输出
- python学习笔记—输入输出
- C学习笔记 文件输入输出
- Python学习笔记——命令行下的输入输出
- Java学习笔记——输入输出
- 【学习笔记】Python的输入输出
- 【C++】【学习笔记】【005】输入输出小结
- 操作符重载——C/C++学习笔记
- 【C++】学习笔记四十三——函数模板
- C/C++文件输入输出操作——FILE*、fstream、windowsAPI
- C/C++文件输入输出操作——FILE*、fstream、windowsAPI
- C/C++文件输入输出操作——FILE*、fstream、windowsAPI
- C/C++文件输入输出操作——FILE*、fstream、windowsAPI
- C/C++文件输入输出操作——FILE*、fstream、windowsAPI
- C/C++文件输入输出操作——FILE*、fstream、windowsAPI
- hadoop学习结构图
- 《A Survey of Image Segmentation techniques》 Thakur 2014文章的阅读思维导图
- 使用API,手工生成 Windows应用程序全过程(图解+文字说明)
- july算法课笔记
- 项目1-三角行雏形设计三角行带参的构造函数
- C++学习笔记55——类模板的输入输出操作符
- Javascript中apply、call、bind
- 深入理解Tomcat系列之七:详解URL请求
- ThreadLocal类源码
- 何为大,世间没有比生命更大,珍惜生命
- c#+windows环境 编写mysql集群服务
- 1个viewController怎么关联2个XIB,一个是iphone的XIB,一个是ipad的xib
- JS学后感受
- HDU 3361 ASCII