C++学习笔记55——类模板的输入输出操作符
2016-03-27 22:14
471 查看
根据重载操作符那一章的规定,输入输出操作符必须作为友元而不是类的成员函数重载。
在类的模板中重载输入输出操作符的方式主要有两种:
在类模板中做friend声明,在模板外做函数定义;
在类模板中定义友元操作符;
执行结果:
因为这里将输出流操作符定义成了一个函数模板,设为友元的仅仅是这个模板的一个实例。
模板形参不可省略。如果将友元声明改成:
则编译报错。
“fatal error LNK1120: 1 个无法解析的外部命令”
因为此时,在模板外定义重定义的输出流操作符与模板类声明的友元输出流操作符不是同一个操作符。
代码总结如下:
当在类内部定义时,三种声明方式都可以。
一旦将输出流定义在另外一个文件中时,就会报错。
比如将1.1的例子分成3个文件friend.h、friend.cpp、main.cpp来实现:
friend.h:
friend.cpp:
main.cpp:
则编译报错:
“fatal error LNK1120: 1 个无法解析的外部命令”
原因没想明白!!!
在类的模板中重载输入输出操作符的方式主要有两种:
在类模板中做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) {} // 整个模板设为友元,OK 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); // Error! //friend ostream& operator<< (ostream& os, const MyScreen<h, w>& ScreenOne);// Error 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; }
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)//OK friend 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; };
friend.cpp:
#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 个无法解析的外部命令”
原因没想明白!!!
相关文章推荐
- c语言:顺序栈的实现
- C++面向对象和流
- 九月十月百度人搜,阿里巴巴,腾讯华为笔试面试八十题(第331-410题) C++版
- C++ const的各种用法
- C++设计模式之适配器(Adapter)模式
- Java客户端与C++服务器端通信
- 2014秋C++第5周项目1參考-见识刚開始学习的人常见错误
- 一个简单的程序教你区分C++中strlen与sizeof
- C++学习日志第三篇
- python 赋值 浅拷贝 深拷贝 与c++ 比较
- 详解MVP矩阵之齐次坐标和ModelMatrix
- 环形缓存区bufferC语言实现
- c++设计模式之原型模式(protoptype)
- C++各数据类型取值范围(备忘)--32位操作系统
- 贪心算法 problem M
- base64编码、解码的C语言实现
- C语言的EOF
- qt c++对象头文件如何相互包含
- 浅谈const限定符——c++
- C++游戏系列1-角色类