文档章节

C++基础——运算符重载友元函数示例

o
 osc_gu9d45li
发布于 2019/04/18 13:21
字数 1132
阅读 8
收藏 0

精选30+云产品,助力企业轻松上云!>>>

一、前言

  其实本人学习C++的目的,只是为了体会OOP设计思想,并为利用System Verilog验证复杂设计做准备。如果想要真正做点软件方面项目级的东西,还需要掌握其他高级语言和库、框架等知识。因此该系列博文仅注重语言基础和设计思想。上一篇该系列博文讲述了C++中基本的类封装,这次利用运算符重载友元函数来体会下C++的灵活性。

二、运算符重载友元函数

  本文同样以《C++ Primer Plus》中的一个简单示例来讲解此内容。场景如下:时间粗劣地分为时和分两部分。需要完成两个时间的相加、时间与倍数的相乘(这个操作不太恰当,凑活看吧)以及显示时间操作。先上代码:

类声明:

 1 #ifndef MYTIME_H_
 2 #define MYTIME_H_
 3 
 4 using std::ostream;
 5 
 6 class Time
 7 {
 8 private:
 9     int hours;
10     int minutes;
11 public:
12     Time();
13     Time(int h,int m=0);
14     void Reset(int h = 0,int m = 0);
15     Time operator+(const Time& t) const;
16     Time operator*(double mult) const;//成员函数
17 
18     friend Time operator*(double m,const Time& t) //友元函数(inline)
19         {return t * m;}
20     friend ostream& operator<<(ostream & os,const Time& t);//<<左侧必须是ostream对象 返回ostream&
21 };
22 #endif
mytime.h

类方法定义:

 1 #include <iostream>
 2 #include "mytime.h"
 3 
 4 Time::Time()
 5 {
 6     hours = minutes = 0;
 7 }
 8 
 9 Time::Time(int h,int m)
10 {
11     hours = h;
12     minutes = m;
13 }
14 
15 void Time::Reset(int h,int m)
16 {
17     hours = h;
18     minutes = m;
19 }
20 
21 Time Time::operator+(const Time& t) const
22 {
23     Time sum;
24     sum.minutes = minutes + t.minutes;
25     sum.hours = hours +t.hours +sum.minutes / 60;
26     sum.minutes %= 60;
27     return sum;
28 }
29 
30 Time Time::operator*(double mult) const
31 {
32     Time result;
33     long totalminutes = hours * mult * 60 + minutes * mult;
34     result.hours = totalminutes / 60;
35     result.minutes = totalminutes % 60;
36     return result;
37 }
38 
39 ostream& operator<<(ostream& os,const Time& t)
40 {
41     os << t.hours << " hours, " << t.minutes << " minutes";
42     return os;
43 }
mytime.cpp

  以上代码的设计原则是:想让Time类对象的相加、与常数相乘以及打印操作与C++内置类型一致。因此+、*、<<三个符号必须进行运算符重载操作,即对此类对象使用这三个运算符时的具体实现细节需重新定义。声明格式为:<返回值类型> operator<op>()。但是这里存在一个问题,成员函数Time operator*(double mult) 在被调用时,类对象必须放置在*符号左侧,也就是说当表达式为m*t(t为Time类对象)时,编译器会报错。使用<<运算符打印Time类对象时同样会遇到此问题。

  为了实现用户友好,使用没有此限制的友元函数重载运算符是个不错的选择。友元函数是类接口的扩展,这类函数虽然不是类成员函数,但可以访问类私有成员。需要注意的一点是:<<输出数据时,左侧必须是ostream类对象。因此重载<<运算符时,必须使函数返回参数中ostream类对象本身才能正确编译cout << A << B;语句。这条语句与(cout << A) << B;等同。

三、应用程序及结果分析

应用程序示例代码:

 1 #include <iostream>
 2 #include "mytime.h"
 3 
 4 using std::endl;
 5 
 6 int main()
 7 {
 8     using std::cout;
 9 
10     Time planning;
11     Time coding(2,40);
12     Time fixing(5,55);
13     Time total;
14     Time adjusted1,adjusted2;
15 
16     cout << "planning time = ";
17     cout << planning << endl;
18 
19     cout << "coding time = ";
20     cout << coding << endl;
21     cout << "fixing time = ";
22     cout << fixing << endl;
23     cout << endl;
24 
25     total = coding + fixing;
26     cout << "coding + fixing = ";
27     cout << total << endl;
28 
29     adjusted1 = total * 1.5;//调用成员函数
30     cout << "total * 1.5 = ";
31     cout << adjusted1 << endl;
32 
33     adjusted2 = 1.5 * total;//调用友元函数
34     cout << "1.5 * total = ";
35     cout << adjusted2 << endl;
36 
37 }
usetime.cpp

  Time类对象planning创建时隐式调用用户定义默认构造函数,而coding和fixing因有参数传递调用第二个构造函数,这正是C++的多态性质。可以看到,打印Time类对象与打印C++内置类型对象无异。重点关注“*”运算符的使用,adjusted1和adjusted2表达式中乘法运算依次调用了成员函数和友元函数。C++编译器同样会自动识别用户的意图。打印结果如图:

  应用程序运行正确,重载的两个Time类对象的加法运算和Time类对象与常数的乘法运算结果无误。之后的两篇博客依次讲述动态内存分配与类继承内容,有错误的地方欢迎指正。

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
C++运算符重载

C++中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使...

五大三粗
2015/05/28
0
0
C++运算符重载Sample

我认为C++最令人惊喜的特点之一就是运算符重载 运算符重载的基础是C++解析运算符时会调用函数 比如 MyObj a, b;a+b;则为a.operator+(b);或者调用友元函数operator+(a, b);要注意重载后的算符...

李三乎
2012/12/02
101
0
C++类或结构作为map的key值

1.只有重载<的类或者结构才能作为map的key值。 string可以作为key值是因为string重载了< 2.如果不重载<会提示如下错误: error C2676: 二进制“<”: “const C”不定义该运算符或到预定义运算...

涩女郎
2015/08/20
34
0
C++ 类模板

文章概述 类模板出现的原因; 几个重要概念的区分; 单个类模板语法: 继承中的类模板语法; 类模板语法知识体系梳理 类模板出现的原因 两个或者多个类的功能是相同的,仅仅是数据类型不同。类模板...

下忍
06/30
0
0
C++基础之运算符重载

一、运算符重载的概念 ⚫ C++中的表达式由运算符和操作数按照规则构成。例如,算术运算符包括加“+”、减“-” 、乘“*” 、除“/”和取模“%”。如果不做特殊处理,则这些算术运算符通常只...

君子生非异也
06/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

vue input 获取焦点

1、首次加载 autofocus="autofocus" #autofocus 属性规定当页面加载时 input 元素应该自动获得焦点。<input type="text" class="rename_box" v-model="current_edit_text" @input="chang......

横着走的螃蟹
9分钟前
0
0
socket链接(底层)

客户端 #socket.socket表明协议并生成链接实例client #client.connect链接到服务器client #循环输入while true #输入的消息 msg = input #client.send(msg.encode())发送信息只能发送比特流进...

onedotdot
16分钟前
18
0
在线讲解一分快3和值怎么计算的

在线讲解一分快3和值怎么计算的老师:【扣 677~90~572】1.The past is gone and static. Nothing we can do will change it. Thefuture is before us and dynamic. Everything we do will af......

yiren081
16分钟前
16
0
hbase学习

简介 数据存储模型及关系型数据库的区别 一般都是牺牲一致性, 最终达到最终一致性 HBase 概念 区别 基础架构 HBASE 原理和操作 写流程 预写入会写入HLog 里面, 通过HLog 来保证数据不丢失 ...

之渊
17分钟前
15
0
网上彩票为什么会有人带你靠谱吗61861585

老师叩:61861585使用默认的随机源随机排列指定的列表。(打乱list中的数据)sort(List<T> list) 进行排序一个人,身边有多少人,就有多大的世界,有什么样的人,就有什么样的世界。这些人素养...

jiukan49
20分钟前
32
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部