前言:本笔记所对应的课程为中国大学mooc中北京大学的程序设计与算法(三)C++面向对象程序设计,主要供自己复习使用,且本笔记建立在会使用c和java的基础上,只针对与c和java的不同来写

运算符重载

运算符重载的基本概念

  1. 目的:希望使对象也能用基本的运算符进行运算。本质上是函数重载。

  2. 可以将运算符重载为普通函数,也可以重载为成员函数。

  3. 一个运算符可以被多次重载,根据实参的具体类型决定调用哪个重载函数。

  4. 格式:

    返回值类型 operator运算符符号(参数表){

    }

实例:

  1. class Complex{
  2. public:
  3. double real, imag;
  4. Complex(double r = 0.0, double i = 0.0):real(r), imag(i){
  5. }
  6. Complex operator-(const Complex & c);
  7. };
  8. Complex operator+(const Complex & c1, const Complex & c2){
  9. return Complex(c1.real+c2.real, c1.imag+c2.imag);
  10. } //当重载为普通函数时,参数个数为运算符目数
  11. Complex Complex::operator-(const Complex & c){
  12. return Complex(real-c.real, imag-c.imag);
  13. } //当重载为成员函数时,参数个数为运算符目数减一
  14. int main(){
  15. Complex a(4, 4), b(1, 1), c, d;
  16. c = a + b; //等价于 c = operator+(a, b);
  17. d = a - b; //等价于 d = a.operator-(b);
  18. }

赋值运算符的重载

赋值运算符只能重载为成员函数。

实例:

  1. # include <iostream>
  2. # include <cstring>
  3. using namespace std;
  4. class String{
  5. private:
  6. char * str;
  7. public:
  8. String():str(new char[1]) { str = 0; }
  9. String(String & s){
  10. str = new char[strlen(s.str)+1];
  11. strcpy(str, s.str);
  12. }
  13. long long adderss() {
  14. return (long long)(&str);
  15. }
  16. const char * c_str() { return str; }
  17. String & operator=(const char * s);
  18. String & operator=(const String & s);
  19. ~String() { delete [] str; }
  20. };
  21. String & String::operator=(const char * s){
  22. //该函数的作用是可以使“obj = "hello"”这样的语句成立(和类型转换构造函数是有区别的)。
  23. delete [] str;
  24. str = new char[strlen(s)+1];
  25. strcpy(str, s);
  26. return * this;
  27. }
  28. String & String::operator=(const String & s){
  29. //这一句是防止出现 s = s 的情况。
  30. if(this == &s)
  31. return * this;
  32. delete [] str;
  33. str = new char[strlen(s.str)+1];
  34. strcpy(str, s.str);
  35. return * this;
  36. }
  37. int main(){
  38. String s;
  39. s = "good luck";
  40. cout << s.c_str() << endl;
  41. //等价于s.operator=("good luck");
  42. //String s2 = "hello";
  43. //这一句是错的,原因:这里的等号不是赋值号,而是“类型转换构造函数”的赋初值法,由于没有写“类型转换构造函数”,因此不会通过。
  44. String s3, s4;
  45. s3 = "first";
  46. s4 = "second";
  47. cout << s3.adderss() << endl;
  48. cout << s4.adderss() << endl;
  49. s3 = s4;
  50. cout << s3.adderss() << endl;
  51. cout << s4.adderss() << endl;
  52. cout << s3.c_str() << endl;
  53. cout << s4.c_str() << endl;
  54. //直接让同一类的两对象相等时,会让s3中每一成员变量的值去等于s4中对应的每一成员变量的值。由于String的成员变量str是指针,因此直接让s3 = s4的话会导致指向同一内存区域,后续进行其他操作时有很大隐患。因此要额外增加一赋值运算符重载函数。
  55. //这里的address()函数用以检查str的地址是否也被赋值
  56. String s5 = s;
  57. cout << s5.c_str() << endl;
  58. //注意这里的等号不是赋值号,而是调用“复制构造函数”赋初值。等价于"String s5(s); "。同理由于String的成员变量str是指针,如果使用默认的“复制构造函数”,会产生上述同样的问题,因此要额外写一个“复制构造函数”。
  59. return 0;
  60. }

注意,对于operator=的返回值类型,应该是String &,而不是void或是String

运算符重载为友元

目的:我们一般将运算符重载为成员函数,但有时会出现不够用的情况,因此需要将运算符重载为友元。

实例:

  1. class Complex{
  2. public:
  3. double real, imag;
  4. Complex(double r = 0.0, double i = 0.0):real(r), imag(i){ }
  5. Complex operator+(double r){
  6. return Complex(real + r, imag);
  7. } //(1)
  8. friend Complex operator+(double r, Complex & c); //(2)
  9. };
  10. Complex operator+(double r, Complex & c){
  11. return Complex(c.real + r, c.imag);
  12. }
  13. int main(){
  14. Complex c;
  15. c = c + 5; //调用(1)
  16. c = 5 + c; //调用(2)
  17. }

可变长数组类的实现

实现方法:重载[]运算符。具体代码暂略。

流插入运算符和流提取运算符的重载

  1. cout是在iostream中定义的,ostream类的对象;cin是istream类的对象。
  2. 一般将重载函数设为全局函数,如果需要用到某对象中的private变量,则可以声明为friend

实例:

  1. # include <iostream>
  2. using namespace std;
  3. class Student{
  4. private:
  5. int age;
  6. friend ostream & operator << (ostream & o, const Student & s);
  7. public:
  8. Student(int n):age(n) {};
  9. };
  10. ostream & operator << (ostream & o, const Student & s){
  11. o << s.age;
  12. return o;
  13. }
  14. int main(){
  15. Student s(5);
  16. cout << s << " years old" << endl;
  17. return 0;
  18. }

类型转换运算符的重载

  1. 注意强制类型转换函数的书写形式,不用写返回类型
  2. 在存在某强制类型转换函数的情况下,如果某些地方使用了该强制类型转换函数可以使程序正确运行,那么会发生隐式的强制类型转换。

实例:

  1. # include <iostream>
  2. using namespace std;
  3. class Complex{
  4. private:
  5. double real, imag;
  6. public:
  7. Complex(double r, double i):real(r), imag(i) {}
  8. operator double (){
  9. return real;
  10. }
  11. //注意强制类型转换函数的书写形式
  12. };
  13. int main(){
  14. Complex c(5, 4);
  15. cout << (double)c << endl;
  16. double n = 2 + c; //这里会发生自动的强制类型转换,等价于n = 2 + c.operator double();
  17. cout << n << endl;
  18. return 0;
  19. }

自增自减运算符的重载

  1. 由于自增自减运算符有前置与后置之分,因此两者写法不同:前置运算符需要作为一元运算符重载,后置运算符需要作为二元运算符重载(增加一个无用的int参数)具体用法如下面实例所示。
  2. 在只写了前置的重载函数,而没有写后置的重载函数时,如果调用后置运算(例如obj++),在vs中会调用前置重载,在dev中会编译出错。

实例:

  1. # include <iostream>
  2. using namespace std;
  3. class Complex{
  4. private:
  5. double real, imag;
  6. public:
  7. Complex(double r, double i):real(r), imag(i){ };
  8. //前置成员函数写法:返回值为对象的引用
  9. Complex & operator ++ (){
  10. ++real;
  11. return *this;
  12. }
  13. //后置成员函数写法:多了一个无用的int参数,返回值为新的对象
  14. Complex operator ++ (int){
  15. Complex temp(*this);
  16. ++real;
  17. return temp;
  18. }
  19. friend Complex & operator -- (Complex & c);
  20. friend Complex operator -- (Complex & c, int);
  21. friend ostream & operator << (ostream & o, const Complex & c);
  22. };
  23. //前置全局函数写法
  24. Complex & operator -- (Complex & c){
  25. --c.real;
  26. return c;
  27. }
  28. //后置全局函数写法
  29. Complex operator -- (Complex & c, int){
  30. Complex temp(c);
  31. --c.real;
  32. return temp;
  33. }
  34. ostream & operator << (ostream & o, const Complex & c){
  35. o << c.real;
  36. return o;
  37. }
  38. int main(){
  39. Complex d(5, 4);
  40. cout << (d++) << ",";
  41. cout << d << ",";
  42. cout << (++d) << ",";
  43. cout << d << endl;
  44. cout << (d--) << ",";
  45. cout << d << ",";
  46. cout << (--d) << ",";
  47. cout << d << endl;
  48. //输出结果应为:
  49. //5,6,7,7
  50. //7,6,5,5
  51. return 0;
  52. }

其他注意事项:

  1. c++不允许定义新的运算符。
  2. 重载后的运算符含义应符合日常习惯。
  3. 运算符重载不改变运算符的优先级。
  4. 一下运算符不可被重载: . .* :: ?: sizeof
  5. 重载运算符() [] -> =时,运算符重载函数必须声明为类的成员函数。

c++学习笔记_4的更多相关文章

  1. servlet学习笔记_4

    一.response.1.response.characterEncoding和response.setContentType("text/html;charset=UTF-8") ...

  2. Java编程思想学习笔记_4(异常机制,容器)

    一.finally语句注意的细节: 当涉及到break和continue语句的时候,finally字句也会得到执行. public class Test7 { public static void m ...

  3. PythonI/O进阶学习笔记_4.自定义序列类(序列基类继承关系/可切片对象/推导式)

    前言: 本文代码基于python3 Content: 1.python中的序列类分类 2. python序列中abc基类继承关系 3. 由list的extend等方法来看序列类的一些特定方法 4. l ...

  4. Flink学习笔记:Flink API 通用基本概念

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  5. flink学习笔记-各种Time

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  6. matlab学习笔记8 基本绘图命令-LineSpec线条设定

    一起来学matlab-matlab学习笔记8 基本绘图命令_4 LineSpec线条设定 觉得有用的话,欢迎一起讨论相互学习~Follow Me 绘图函数接受线条设定作为参数并相应地修改生成的图形.您 ...

  7. matlab学习笔记4--导入和导出Internet数据

    一起来学matlab-matlab学习笔记4 数据导入和导出_4 导入和导出Internet数据 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合 ...

  8. Learning hard 学习笔记

    第一章 你真的了解C#吗 1.什么是C#, 微软公司,面向对象,运行于.NET Framework之上, 2.C#能编写哪些应用程序, Windows应用桌面程序,Web应用程序,Web服务, 3.什 ...

  9. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

随机推荐

  1. Linux基础之bash shell介绍及基本特性

    今天继续讲Linux基础知识,内容是关于bash shell的.分享以下bash shell的相关知识,例如基本特性等.  1.8)bash shell的介绍 1.8.1)什么是bash shell ...

  2. Jquery第一次考核

    1. 什么是JS JavaScript 缩写.一种计算机脚本语言 JavaScript是一种动态.弱类型.基于原型的语言,通过浏览器可以直接执行 2. JS三大组成部件 ECMAScript DOM ...

  3. Oracle_InstantClient 及PL/SQL Developer工具的安装

    一.下载 InstantClient 地址: http://www.oracle.com/technology/software/tech/oci/instantclient/index.html i ...

  4. 关于程序null值的见解

    今天遇到了一个问题,查询一条数据,返回用list接,发现少了2个值(ssh框架).执行SQL少的这两个字段的值为null.上图说明一下: 可以看到第一次查询没有角标38.39的值. 是同一条SQL,第 ...

  5. 【0807 | Day 10】字符编码以及Python2/3编码的区别

    一.计算机基础 计算机组成:CPU.内存.硬盘 CPU:控制程序运行(从内存中取出文本编辑器的数据存入内存) 内存:运行程序 硬件:存储数据 二.文本编辑器存取文件的原理 比如计算机只能识别0和1,文 ...

  6. Spring 集成Kafka(完整版)

    前面的文章我们已经完成了Kafka基于Zookeeper的集群的搭建了.Kafka集群搭建请点我.记过几天的研究已经实现Spring的集成了.本文重点 jar包准备 集成是基于spring-integ ...

  7. 100天搞定机器学习|Day16 通过内核技巧实现SVM

    前情回顾 机器学习100天|Day1数据预处理100天搞定机器学习|Day2简单线性回归分析100天搞定机器学习|Day3多元线性回归100天搞定机器学习|Day4-6 逻辑回归100天搞定机器学习| ...

  8. 浅谈 JavaScript 垃圾回收机制

    github 获取更多资源 https://github.com/ChenMingK/WebKnowledges-Notes 在线阅读:https://www.kancloud.cn/chenmk/w ...

  9. powerdesigner16.6版本resource的重复使用

    今天早上遇到想要重复使用resource ,但是发现powerdesigner16.6版本跟16.5版本有关重复使用name的设置已经不一样了,网上找了好久没找到,软件上找了好久也没找到相应的设置. ...

  10. SpringBoot优雅地配置日志

    本文主要给大家介绍SpringBoot中如何通过sl4j日志组件优雅地记录日志.其实,我们入门 JAVA 的第一行代码就是一行日志,那你现在还在使用System.out.println("H ...