左移运算符重载
#include<bits/stdc++.h>
using namespace std;
class Person
{friend ostream & operator<<(ostream &cout,Person &p);
public:Person(int a,int b){m_A = a;m_B = b;}
private://利用成员函数重载 左移运算符 //p.operaor<<(cout) 简化版本p<<cout//不会利用成员函数重载<<运算符,因为无法实现cout在左侧//void operaor<<(cout)//{ } int m_A;int m_B;};
ostream & operator<<(ostream &cout,Person &p)//本质为 operator<<(cout,p) 简化 cout<<p
{cout<<"m_A= "<<p.m_A<<" m_B= "<<p.m_B;
}
void test01()
{Person p(10,20);cout<<p<<endl;
}
int main(){test01();return 0;
}
为什么重载
<<
运算符时需要返回ostream&
类型的引用呢?
1. 链式调用
返回 ostream&
类型的引用允许我们实现链式调用,例如:
cout << p1 << p2 << p3;
这种语法会被编译器解释为:
(((cout << p1) << p2) << p3);
每次 <<
运算符重载函数返回的都是 cout
对象的引用,这样才能够连续地将多个对象输出到同一个 cout
流中。
2. 流式输出
C++ 中的 <<
运算符经常用于实现流式输出的效果,例如 cout << "Hello" << " " << "World" << endl;
。每个 <<
运算符都将数据追加到 cout
流中,因此 <<
运算符的返回类型必须是 ostream&
,以确保可以继续将数据输出到同一个流中。
3. 返回类型为什么是引用
返回引用而不是值的另一个原因是为了避免不必要的对象复制。如果每次 <<
运算符返回的是 ostream
对象而不是引用,那么在每次函数调用结束时会产生一个临时的 ostream
对象副本,这不仅效率低下,而且破坏了期望的输出顺序。
因此,返回 ostream&
类型的引用是为了支持链式调用和流式输出的正确性和效率。这也是 C++ 中惯例和推荐的做法。
为什么要将 m_A 和 m_B 私有化?
-
封装性和安全性: 将数据成员声明为私有的意味着它们只能被
Person
类的成员函数访问,而外部代码不能直接访问或修改这些成员。这样做提高了类的封装性,避免了数据被不相关的代码误用或修改。 -
数据访问控制: 通过公开的构造函数
Person(int a, int b)
,类的使用者可以在创建对象时初始化m_A
和m_B
,而后续的访问和修改必须通过类的公有接口或者友元函数来进行,从而保证了数据的安全性和一致性。 -
友元函数访问: 尽管
m_A
和m_B
是私有的,但operator<<
被声明为Person
类的友元函数,可以访问Person
对象的私有成员。这样做既保留了数据的封装性,又允许特定函数或类进行必要的数据操作,例如输出Person
对象的信息。