C++ 流插入和流提取运算符的重载的实现

所属分类: 软件编程 / C 语言 阅读数: 112
收藏 0 赞 0 分享

01 流插入<<运算符的重载

C++ 在输出内容时,最常用的方式:

std::cout << 1 <<"hello";

问题:

  • 那这条语句为什么能成立呢?
  • cout 是什么?"<<" 运算符能用在 cout 上呢?

原因:

  • 实际上,cout 是在 iostream 头文件中定义的 ostream 类的对象。
  • "<<" 能够用在 cout 上是因为,在 ostream 类对 "<<" 进行了重载。

对于std::cout << 1 <<"hello";这条语句,有可能按以下的方式重载成 ostream 类的成员函数:

ostream & ostream::operator<<(int n)
{
  .... // 输出n整型的代码
  return *this;
}

ostream & ostream::operator<<(const char * s)
{
  .... // 输出s字符串的代码
  return *this;
}

  • std::cout << 1;语句,等价于cout.operator<<(1);
  • std::cout << "hello";语句,等价于cout.operator<<("hello");
  • std::cout << 1 <<"hello";语句,等价于( cout.operator<<(1) ).operator<<("hello");

02 流插入<<运算符重载的例子

假定我们要想把某个对象里的内容进行打印输出,那么我们可以重载 ostream 类的流插入 << 运算符。

下面以 CStudent 类作为例子:

class CStudent // 学生类
{
public:
  // 构造函数
  CStudent(int id = 0, int age = 0, string name = ""):m_id(id), m_age(age), m_name(name) { }
  
  // 将该函数声明成友元函数
  // 目的是使得函数可以访问CStudent类的私有成员变量
  friend ostream & operator<<(ostream & o, const CStudent & s);
  
private:
  int m_age;   // 年龄
  int m_id;    // ID号
  string m_name; // 名字
};

// 重载ostream对象的流插入<<运算符函数
// 目的是使得能打印输出CStudent对象的信息
ostream & operator<<(ostream & o, const CStudent & s)
{
  o << s.m_id << "," << s.m_age << "," << s.m_name;
  return o;
}

int main()
{
  CStudent stu(1, 20, "小林coding");
  std::cout << stu ; // 输出std对象的全部信息
  
  return 0;
}

输出结果:

1,20,小林coding

需要注意是 ostream & operator<<(ostream & o, const CStudent & s) 函数是全局的,所以函数的第一个参数必须要传入 ostream 的对象,并且 CStudent 类需要将此函数声明成友元函数,使得函数可以访问 CStudent 类的私有成员变量。

03 流提取>>运算符重载的例子

还是以 CStudent 类作为例子,假设想通过键盘的输入的内容,来初始化对象,则我们可以重载 istream 类的流提取 >> 运算符。

class CStudent // 学生类
{
public:

  // 构造函数
  CStudent(int id = 0, int age = 0, string name = ""):m_id(id), m_age(age), m_name(name) { }
  
  // 将该函数声明成友元函数
  // 目的是使得函数可以访问CStudent类的私有成员变量
  friend ostream & operator<<(ostream & o, const CStudent & s);
  
  // 将该函数声明成友元函数
  // 目的是使得函数可以给CStudent类的私有成员变量进行赋值
  friend istream & operator>>(istream & is, CStudent & s);
  
private:
  int m_age;   // 年龄
  int m_id;    // ID号
  string m_name; // 名字
};

// 重载ostream对象的流插入<<运算符函数
// 目的是使得能打印输出CStudent对象的信息
ostream & operator<<(ostream & o, const CStudent & s)
{
  o << s.m_id << "," << s.m_age << "," << s.m_name;
  return o;
}

// 重载istream对象的流提取>>运算符函数
// 目的是使得初始化CStudent对象的内容
istream & operator>>(istream & is, CStudent & stu)
{
  string inputStr;
  is >> inputStr;
  
  int pos = inputStr.find(",", 0);     // 查找首次出现逗号的位置
  string tmpStr = inputStr.substr(0, pos); // 截取从0到pos位置的字符串
  stu.id = atoi(tmpStr.c_str());      // atoi可以将char*类型的内容转成int类型
  
  int pos2 = inputStr.find(",", pos + 1);      // 查找第二次出现逗号的位置
  tmpStr = inputStr.substr(pos + 1, pos2 - pos -1); // 取出age的值
  stu.age = atoi(tmpStr.c_str());          // atoi可以将char*类型的内容转成int类型
  
  tmpStr = inputStr.substr(pos2 + 1, inputStr.length() - pos2 - 1); // 取出name的值
  stu.name = tmpStr;
  
  return is;
}

int main()
{
  CStudent stu;
  
  // 将输入的信息,初始化stu对象
  cin << stu;
  
  // 输出std对象的信息
  cout >> stu;
  
  return 0;
}

输入内容和输出内容:

// 输入内容:
1,20,小林coding

// 输出内容:
1,20,小林coding

04 小结

要想流插入 << 运算符和流提取 >> 运算符能针对自定义的对象,那么我们就需要重载针对该对象的 ostream 类的 << 运算符 和 istream 的 >> 运算符,并且只能重载成全局的函数,然后在 CStudent 类里需要把上面的两个重载函数声明成友元函数,使得两个重载的函数可以访问和赋值 CStudent 类里的私有成员函数。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多