C++ Primer Plus第六版-第十一章-学习笔记
第 11 章 使用类
不要觉得必须使用所有的特性,不要在第一次学习时就试图使用所有的特性。 ——Bjarne Stroustrup
11.1 运算符重载
要重载运算符,需要使用被称为运算符函数的特殊函数形式。
operator p(argument-list)
如果distric2、sid和sara都是Salesperson类对象,可以编写这样的等式:
distric2 = sid + sara;
distric2 = sid.operator + (sara); //相应的运算符函数替换上述运算符,隐式使用sid,显示使用sara
11.2 计算时间:一个运算符重载示例
不要返回指向局部变量或临时变量的引用。函数执行完毕之后,局部变量和临时对象将消失,引用将指向不存在的数据。
重载限制
- 重载后的运算符必须至少有一个操作数是用户定义的类型
- 使用运算符时不能违反运算符原来的句法规则
- 不能创建新运算符
- 不能重载下面的运算符:P387
- 表11.1中的大多数运算符都可以通过成员或非成员函数进行重载,但下面的运算符只能通过成员函数进 行重载:
- =:赋值运算符
- ():函数调用运算符。
- []:下标运算符
- ->:通过指针访问类成员的运算符
11.3 友元
- 友元函数
- 友元类
- 友元成员函数
有一类特殊的非成员函数可以访问类的私有成员,它们被称为友元函数。
11.3.1 创建友元
创建友元函数的第一步是将其原型放在类声明中,并在原型声明前加上关键字friend:
friend Time operator*(double m, const Time& t); //goes in class declaration
- 虽然operator*()函数是在类声明中声明的,但它不是成员函数,因此不能使用成员运算符来调用;
- 虽然operator*()函数不是成员函数,但它与成员函数的访问权限相同。
第二步是编写函数定义。因为它不是成员函数,所以不要使用Time::限定符。另外,不要在定义中使用关键字friend,定义如下:
Time operator*(double m, const Time& t)
{
}
类的友元函数是非成员函数,其访问权限与成员函数相同。
Time operator*(double m, const Time& t)
{
return t * m;
} //这个版本将Time对象t作为一个整体使用,让成员函数来处理私有值,因此不必是友元。
//然而作为友元也是一个好主意!
如果要为类重载运算符,并将非类的项作为其第一个操作数,则可以用友元函数来翻转操作数的顺序
11.3.2 常用的友元: 重载<< 运算符
- <<的第一种重载版本
使用友元函数,可以像下面这样重载运算符:
void operator<<(ostream& os, const Time& t)
{
os << t.hours << " hours, " << t.minutes << " minutes";
} //这样可以使用下面的语句
cout << trip;
- <<的第二种重载版本
前面介绍的实现存在一个问题。不允许像通常那样将重新定义的<<运算符与cout一起使用
可以对友元函数采用相同的方法。只要修改operator<<()函数,让它返回ostream对象的引用即可:
ostream& operator<<(ostream& os, const Time& t)
{
os << t.hours << " hours, " << t.minutes << " minutes";
return os;
}
11.4 重载运算符: 作为成员函数还是非成员函数
一般来说,非成员函数应该是友元函数,这样它才能直接访问类的私有数据。
加法运算符需要两个操作数。对于成员函数版本来说,一个操作数通过this指针隐式地传递,另一个操作数作为函数参数显示传递;对于友元版本来说,两个操作数都作为参数来传递。
11.6 类的自动转换和强制类型转换
只接受一个参数的构造函数才能作为转换函数。若有两个参数,则当为第二个参数提供默认值时,它便可用于转换。
将构造函数用作自动类型转换函数似乎是一项不错的特性。C++新增了关键字explicit,用于关闭这种自动特性
只接受一个参数的构造函数定义了从参数类型到类类型的转换。
如果在声明中使用了关键字explicit,则Stonewt(double)将只能用于显示强制类型转换,否则还可以用于下面的隐式转换。
- 将Stonewt对象初始化为double值时。
- 将double值赋给Stonewt对象时。
- 将double值传递给接受Stonewt参数的函数时。
- 返回值被声明为Stonewt的函数试图返回double值时。
- 在上述任意一种情况下,使用可转换为double类型的内置类型时。
转换函数
构造函数只用于从某种类型到类类型的转换。
转换函数是用户定义的强制类型转换,可以像使用强制类型转换那样使用它们。用于将类对象转换为其他类型
如何创建转换函数呢:
operator typeName();
- 转换函数必须是类方法
- 转换函数不能指定返回类型;
- 转换函数不能有参数。
实现加法时的选择
要将double量和Stonewt量相加,有两种选择:
- 让Stonewt(double)构造函数将double类型的参数转换为Stonewt类型的参数,然后将下面的函数定义为友元函数:
operator+(const Stonewt&, const Stonewt& )
- 将加法运算符重载为一个显示使用double类型参数的函数:
Stonewt operator+(double x); //member function
friend Stonewt operator+(double x, Stonewt& s);
第一种方法程序简短,但时间和内存开销大
第二种方法运行速度快
【华为OD机试真题】可以转到CSDN相关专栏订阅学习:https://blog.csdn.net/weixin_45541762/article/details/129903356
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】