草庐IT

C++基础-5-运算符重载(加号,左移,递增,赋值,关系,函数调用)

LYH-win 2023-03-28 原文

5. 运算符重载

 

5.1  加号运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 
 4 // 加号运算符重载
 5 
 6 class Person {
 7 public:
 8     //1. 成员函数重载“+”
 9     Person operator+(Person& p) {
10         Person temp;
11         temp.m_A = this->m_A + p.m_A;
12         temp.m_B = this->m_B + p.m_B;
13         return temp;
14     }
15 
16     int m_A;
17     int m_B;
18 };
19 
20 //2. 全局函数重载“+”
21 Person operator+(Person& p1, Person& p2) {
22     Person temp;
23     temp.m_A = p1.m_A + p2.m_A;
24     temp.m_B = p2.m_B + p2.m_B;
25     return temp;
26 }
27 
28 void test01() {
29     Person p1;
30     p1.m_A = 10;
31     p1.m_B = 20;
32 
33     Person p2;
34     p2.m_A = 10;
35     p2.m_B = 20;
36 
37     Person p3 = p1 + p2;
38 
39     cout << "p1 + p1:" << p3.m_A << " " << p3.m_B << endl;
40 
41 }
42 
43 int main() {
44 
45     test01();
46 
47     system("pause");
48 
49     return 0;
50 }
51 
52 
53 // 总结
54 // 对已有的运算符进行重新定义。赋予其另一种功能,以适应不同的数据类型
55 // 运算符重载也可以发生函数重载

 

5.2 左移运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 
 4 
 5 class Person {
 6     friend ostream& operator<<(ostream& cout, Person& p);
 7 public:
 8     Person(int a, int b) {
 9         m_A = a;
10         m_B = b;
11     }
12 public:
13 
14     //1. 利用成员函数重载“左移”运算符
15     // p.operator << (cout) 简化版本 p << cout
16     // 不会利用成员函数重载<<运算符,因为无法实现<<在左侧
17     // 故不能使用成员函数的方法!!
18 
19     //int m_A; // public属性,可以类外访问
20     //int m_B;
21 
22 private:
23     int m_A; //如果是私有属性,可以通过friend方法解决
24     int m_B;
25 };
26 
27 //2. 利用全局函数重载“左移<<”运算符
28 ostream& operator<<(ostream& cout, Person &p) { // 本质 operator << (cout, p) 简化 cout << p
29     // cout的数据类型是ostream,可以转到定义去查看
30     cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
31     return cout; //链式编程思想,返回值类型为ostream
32 }
33 
34 void test01() {
35     Person p(10, 20);
36     //p.m_A = 10;
37     //p.m_B = 10;
38 
39     cout << p << endl;;
40 }
41 
42 int main() {
43 
44     test01();
45 
46     system("pause");
47 
48     return 0;
49 }

 

5.3 递增运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 
 4 // 递增(递减)运算符重载
 5 
 6 class MyInteger {
 7     friend ostream& operator<<(ostream& cout, MyInteger myint);
 8 public:
 9     MyInteger() {
10         m_Num = 0;
11     }
12 
13     // 重载前置++运算符
14     // 返回引用是为了一直对一个数据进行递增操作
15     MyInteger& operator++() {
16         // 先进行++运算
17         m_Num++;
18 
19         //再将自身返回
20         return *this;
21     }
22 
23     // 重载后置++运算符, int代表占位参数,区分前置与后置递增
24     // 后置递增返回值,不能返回引用,因为是个局部变量,不能返回局部变量的引用
25     MyInteger operator++(int) {
26         // 先记录当时结果
27         MyInteger temp = *this;
28 
29         // 后 递增操作
30         m_Num++;
31         // 最后,将记录的结果返回
32 
33         return temp;
34     }
35 
36 private:
37     int m_Num;
38 
39 };
40 
41 // 全局函数实现“<<”运算符重载
42 ostream& operator<<(ostream& cout, MyInteger myint) {
43     cout << myint.m_Num;
44     return cout;
45 
46 }
47 
48 void test01() {
49 
50     MyInteger myint;
51 
52     cout << ++myint << endl;
53 
54 }
55 
56 void test02() {
57     MyInteger myint;
58     
59     cout << myint++ << endl;
60     cout << myint << endl;
61 
62 }
63 
64 int main() {
65 
66     //test01();
67     test02();
68 
69     system("pause");
70 
71     return 0;
72 }

 

5.4 赋值运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 
 4 // 赋值运算符重载
 5 class Person {
 6 public:
 7     Person(int age) {
 8         m_Age = new int(age);
 9     }
10 
11     //重载 赋值运算符
12     Person& operator=(Person &p) {
13         //编译器提供的是如下的浅拷贝
14         // m_Age = p.m_Age;
15 
16         //首先应该判断是否存在有属性在堆区,如果有,要先释放干啥,然后进行深拷贝
17         if (m_Age != NULL) {
18             delete m_Age;
19             m_Age = NULL;
20         }
21 
22         // 然后进行深拷贝操作
23         m_Age = new int(*p.m_Age);
24 
25         // 要返回对象本身
26         return *this;
27 
28     }
29 
30     ~Person() {
31         if (m_Age != NULL) {
32             delete m_Age;
33             m_Age = NULL;
34         }
35     }
36 
37     int* m_Age;
38 };
39 
40 
41 
42 void test01() {
43     Person p1(18);
44 
45     Person p2(20);
46 
47     Person p3(30);
48 
49     p2 = p1;  // 赋值运算操作
50 
51     p3 = p2 = p1; //注意返回值类型
52 
53     cout << "p1的年龄为:" << *p1.m_Age << endl;
54     cout << "p2的年龄为:" << *p2.m_Age << endl;
55     cout << "p3的年龄为:" << *p3.m_Age << endl;
56 }
57 
58 int main() {
59 
60     test01();
61 
62     system("pause");
63 
64     return 0;
65 }
66 
67 // 总结
68 // C++默认给一个类添加4个函数
69 // 默认构造,默认析构函数
70 // 默认拷贝(对属性进行值拷贝)
71 // 
72 // 赋值运算符operator=对属性进行值拷贝
73 // 
74 // 如果有属性指向堆区,做赋值操作时会出现深浅拷贝的问题
75 // 如果出现堆区数据,要通过深拷贝方法解决
76 // 

 

5.5 关系运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 
 4 // 关系运算符重载
 5 // 可以让自定义的两个类型对象进行对比操作
 6 
 7 class Person {
 8 public:
 9     Person(string m_Name, int age) {
10         m_Age = age;
11         m_Name = m_Name;
12     }
13 
14     //重载 == 号
15     bool operator==(Person& p) {
16         if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
17             return true;
18         }
19         return false;
20     }
21 
22     string m_Name;
23     int m_Age;
24 
25 };
26 
27 void test01() {
28     Person p1("Tom", 18);
29 
30     Person p2("Tom", 18);
31 
32     if (p1 == p2) {
33         cout << "p1和p2是相等的!" << endl;
34 
35     }
36 
37 }
38 
39 int main() {
40 
41     test01();
42 
43     system("pause");
44 
45     return 0;
46 }

 

5.6 函数调用运算符重载

 1 #include<iostream>
 2 using namespace std;
 3 #include<string>
 4 
 5 
 6 // 函数调用()运算符重载
 7 // 由于重载后使用的方式非常想函数的调用,因此也成为“仿函数”
 8 // 仿函数没有固定写法,非常的灵活
 9 
10 class MyPrint {
11 public:
12     void operator()(string text) {
13         cout << text << endl;
14 
15     }
16 };
17 
18 class Myadd {
19 public:
20     int operator()(int a, int b) {
21         return a + b;
22     }
23 };
24 
25 void test01() {
26     // 重载的 () 操作符 也称为仿函数
27     MyPrint myfunc;
28     myfunc("hello world");
29 
30     // 匿名函数对象
31     cout << Myadd()(10, 20) << endl;
32 
33 }
34 
35 int main() {
36 
37     test01();
38 
39     system("pause");
40 
41     return 0;
42 }

 

参考《黑马程序员》C++教程

有关C++基础-5-运算符重载(加号,左移,递增,赋值,关系,函数调用)的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  3. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  4. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  5. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

    我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

  6. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  7. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  8. 软件测试基础 - 2

    Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功

  9. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  10. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

随机推荐