1.Cpp中的重载运算符和重载函数

  • C++允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。当调用一个重载函数或重载运算符时,编译器通过调用使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策

2.函数重载

  • 在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。函数重载的实例如下,其中print()函数就是重载函数:

        #include "iostream"#include "cstring"using namespace std;class A{public: void print(int i){cout << "整数为: " << i << endl;}void print(double d){cout << "浮点数为: " << d << endl;}void print(char c[]){cout << "字符串为: " << c << endl;}};int main(){A a;// 输出整数a.print(2);// 输出浮点数a.print(3.14);// 输出字符串char c[] = "Hello Curry";a.print(c);cout << "----------------------------------------------\n";return 0;}
    

3.运算符重载

  • 可以重定义或重载大部分C++内置的运算符。这样,就能使用自定义类型的运算符。重载的运算符是带有特殊名称的函数,函数名是由关键字operator和其后面要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。例如:

        Box operator+(const Box&);
    
  • 声明加法运算符用于把两个Box对象相加,返回最终的Box对象。大多数的重载运算符可被定义为普通的非成员函数或者被定义为类成员函数。如果我们定义上面的函数为类的非成员函数,那么我们需要为每次操作传递两个参数,如下所示:
        Box operator+(const Box&, const Box&);
    
  • 运算符重载的实例,对象作为参数进行传递,对象的属性使用 this 运算符进行访问,如下所示:
        // 运算符重载class Box{public:double getVolume(){return length * width * height;}void setLength(int len){length = len;}void setWidth(int wid){width = wid;}void setHeight(int hei){height = hei;}// 运算符重载:用于把两个box对象相加Box operator+(const Box& b){Box box;box.length = this->length + b.length;box.width = this->width + b.width;box.height = this->height + b.height;return box;}private:int length;int width;int height;};int main(){Box box1;Box box2;Box box3;double volume = 0.0;box1.setLength(6.0);box1.setWidth(7.0);box1.setHeight(5.0);box2.setLength(12.0);box2.setWidth(13.0);box2.setHeight(10.0);volume = box1.getVolume();cout << "box1的体积是: " << volume << endl;volume = box2.getVolume();cout << "box2的体积是: " << volume << endl;box3 = box1 + box2;volume = box3.getVolume();cout << "box3的体积是: " << volume << endl;cout << "----------------------------------------------\n";return 0;}
    

4.可重载运算符与不可重载运算符

  • 可重载运算符列表如下:
  • 不可重载运算符列表如下:

5.运算符重载实例

5.1 一元运算符重载

  • 一元运算符只对一个操作数进行操作,下面是一元运算符的实例:

    • ++和--运算符重载

          // ++与--运算符重载class Time{private:int hours;int minutes;public:Time(){hours = 0;minutes = 0;}Time(int h, int m): hours(h), minutes(m){cout << "Time类对象的构造函数\n";}void display(){cout << "H:" << hours << " M:" << minutes << endl;}// 重载前缀递增++运算符Time operator++(){++minutes;  // 对象加 1if(minutes >= 60){++hours;minutes-= 60;}return Time(hours, minutes);}// 重载后缀递增++运算符Time operator++(int){Time T(hours, minutes);  // 保存原始值++minutes;  // 对象加 1if(minutes >= 60){++hours;minutes-= 60;}return T;  // 返回旧的原始值}};
      
      • ++和--运算符重载注意点:

        • 递增和递减一般是改变对象的状态,所以一般是重载为成员函数
        • 重载递增递减,一定要和指针的递增递减区分开。因为这里的重载操作的是对象,而不是指针(由于指针是内置类型,指针的递增递减是无法重载的),所以一般情况的递增递减是操作对象内部的成员变量。
        • 递增和递减分为前置和后置情况,a = ++b;(前置), a = b++;(后置)。因为符号一样,所以给后置版本加一个int形参作为区分,这个形参是0,但是在函数体中是用不到的,只是为了区分前置后置。例如:
              // ++与--运算符重载注意的点class CA{public:int pos;// 前置++就是增加当前对象的pos的值,并返回当前对象CA operator++(){pos++;return *this;}// 后置++就是增加当前对象的pos的值,并返回增加pos之前的对象CA operator++(int){CA temp = *this;++*this;return temp;}};CA ca,cb;ca.pos = 1;cb = ca++;cout << "cb = " << cb.pos << endl;cb = ++ca;cout << "cb = " << cb.pos << endl;
          
    • 一元减运算符,即负号(-)
          // 重载一元减运算符-class Distance{private:int feet;int inches;public:Distance(){feet = 0;inches = 0;}Distance(int f, int i): feet(f), inches(i){cout << "Distance类对象的构造函数\n";}void displayDistance(){cout << "F = " << feet << " I = " << inches << endl;}// 重载运算符-Distance operator-(){feet = -feet;inches = -inches;return Distance(feet, inches);}};Distance D1(10, 11), D2(-5, 11);-D1;D1.displayDistance();-D2;D2.displayDistance();
      
    • 逻辑非运算符(!)

5.2 二元运算符重载

  • 二元运算符需要两个参数,下面是二元运算符的实例。我们平常使用的加运算符( + )、减运算符( - )、乘运算符( * )和除运算符( / )都属于二元运算符。就像加(+)运算符。

        class Box{public:double getVolume(){return length * width * height;}void setLength(int len){length = len;}void setWidth(int wid){width = wid;}void setHeight(int hei){height = hei;}// 运算符重载:用于把两个box对象相加Box operator+(const Box& b){Box box;box.length = this->length + b.length;box.width = this->width + b.width;box.height = this->height + b.height;return box;}private:int length;int width;int height;};int main(){Box box1;Box box2;Box box3;double volume = 0.0;box1.setLength(6.0);box1.setWidth(7.0);box1.setHeight(5.0);box2.setLength(12.0);box2.setWidth(13.0);box2.setHeight(10.0);volume = box1.getVolume();cout << "box1的体积是: " << volume << endl;volume = box2.getVolume();cout << "box2的体积是: " << volume << endl;box3 = box1 + box2;volume = box3.getVolume();cout << "box3的体积是: " << volume << endl;cout << "----------------------------------------------\n";return 0;}
    

5.3 关系运算符重载

  • C++ 语言支持各种关系运算符( < 、 > 、 <= 、 >= 、 == 等等),它们可用于比较 C++ 内置的数据类型,可以重载任何一个关系运算符,重载后的关系运算符可用于比较类的对象。

        class Distance{private:int feet;int inches;public:Distance(){feet = 0;inches = 0;}Distance(int f, int i): feet(f), inches(i){cout << "Distance类对象的构造函数\n";}void displayDistance(){cout << "F = " << feet << " I = " << inches << endl;}// 重载关系运算符<bool operator < (const Distance& d){if(feet < d.feet)return true;if(feet == d.feet && inches < d.inches)return true;return false;}     };if (D1 < D2)cout << "D1 < D2\n";else    cout << "D1 > D2\n";
    

5.4 输入输出运算符重载

  • C++ 能够使用流提取运算符>>和流插入运算符<<来输入和输出内置的数据类型。可以重载流提取运算符和流插入运算符来操作对象等用户自定义的数据类型。需要把运算符重载函数声明为类的友元函数,这样我们就能不用创建对象而直接调用函数。

        class Distance{private:int feet;int inches;public:Distance(){feet = 0;inches = 0;}Distance(int f, int i): feet(f), inches(i){cout << "Distance类对象的构造函数\n";}void displayDistance(){cout << "F = " << feet << " I = " << inches << endl;}// 重载输入输出运算符friend ostream &operator<<(ostream &output, const Distance& D){output << "F = " << D.feet << " I = " << D.inches << endl;return output;}friend istream &operator>>(istream &input, Distance &D){input >> D.feet >> D.inches;return input;}};Distance D3(11, 10), D4(3, 2), D5;cout << "请输入目标值D5 = ";cin >> D5;cout << "D3 = " << D3 << endl;cout << "D4 = " << D4 << endl;cout << "D5 = " << D5 << endl;
    

5.5 赋值运算符重载

  • 像其他运算符一样,您可以重载赋值运算符( = ),用于创建一个对象,比如拷贝构造函数。

        class Distance{private:int feet;int inches;public:Distance(){feet = 0;inches = 0;}Distance(int f, int i): feet(f), inches(i){cout << "Distance类对象的构造函数\n";}void displayDistance(){cout << "F = " << feet << " I = " << inches << endl;}// 赋值运算符重载void operator=(const Distance& D){feet = D.feet;inches = D.inches;}};D1 = D2;cout << "D1: " << D1 << endl;D1.displayDistance();
    
  • 当用用户自定义类型变量向内置类型变量赋值时,可以使用自定义类型的隐式转换
        class Int{private:int n;public:Int(int i){cout << "Int对象的构造函数\n";};operator int(){  // 这里就是隐式转换声明,应注意到它与运算符重载的不同之处return n;}};Int int_obj(3);int i = int_obj;  // 隐式调用转换函数cout << "i = " << i << endl;cout << "int_obj = " << int_obj << endl;  // 由于未重载Int的<<操作符,将隐式调用转换函数
    

5.6 函数调用运算符重载()

  • 函数调用运算符()可以被重载用于类的对象。当重载()时,不是创造了一种新的调用函数的方式。相反地,这是创建一个可以传递任意数目参数的运算符函数。

        class Distance{private:int feet;int inches;public:Distance(){feet = 0;inches = 0;}Distance(int f, int i): feet(f), inches(i){cout << "Distance类对象的构造函数\n";}void displayDistance(){cout << "F = " << feet << " I = " << inches << endl;}// 重载函数调用运算符Distance operator()(int a, int b, int c){Distance D;// 进行随机计算D.feet = a + c + 10;D.inches = b + c + 100;return D;}};Distance D6;D6 = D1(10, 10, 10);cout << "D6: " << D6 << endl;
    

5.7 下标运算符重载[]

  • 下标操作符[]通常用于访问数组元素,重载该运算符用于增强操作C++数组的功能

        // 下标运算符重载const int SIZE = 10;class safearray{private:int arr[SIZE];public:safearray(){register int i;for(i = 0; i < SIZE; i++)arr[i] = i;}// 下标运算符重载int & operator[](int i){if(i > SIZE){cout << "索引超过最大值: ";return arr[0];}return arr[i];}      };safearray sa;cout << "sa[2] = " << sa[2] << endl;cout << "sa[5] = " << sa[5] << endl;cout << "sa[12] = " << sa[12] << endl;
    

5.8 类成员访问运算符->重载

  • 类成员访问运算符->可以被重载,但它较为麻烦。它被定义用于为一个类赋予"指针"行为。运算符->必须是一个成员函数。如果使用了->运算符,返回类型必须是指针或者是类的对象。运算符->通常与指针引用运算符*结合使用,用于实现"智能指针"的功能。这些指针是行为与正常指针相似的对象,唯一不同的是,当通过指针访问对象时,它们会执行其他的任务。比如,当指针销毁时,或者当指针指向另一个对象时,会自动删除对象。

        // 类成员访问运算符->class OO{static int i,j;public:void f() const{  // 常函数cout << i++ << endl;}void g() const{cout << j++ << endl;}};// 静态成员定义int OO::i = 10;int OO::j = 12;// 为上面的类实现一个容器class ObjContainer {vector<OO*> a;public:void add(OO* obj){ a.push_back(obj);  // 调用向量的标准方法}friend class SmartPointer;};// 实现智能指针,用于访问类 Obj 的成员class SmartPointer {ObjContainer oc;int index;public:SmartPointer(ObjContainer& objc){ oc = objc;index = 0;}// 返回值表示列表结束bool operator++() // 前缀版本{ if(index >= oc.a.size() - 1) return false;if(oc.a[++index] == 0) return false;return true;}bool operator++(int) // 后缀版本{ return operator++();}// 重载运算符 ->OO* operator->() const {if(!oc.a[index]){cout << "Zero value";return (OO*)0;}return oc.a[index];}};const int sz = 10;OO o[sz];ObjContainer oc;for(int i = 0; i < sz; i++){oc.add(&o[i]);}SmartPointer sp(oc); // 创建一个迭代器do {sp->f(); // 智能指针调用sp->g();} while(sp++);
    

6.运算符重载注意的点

  • a.运算重载符不可以改变语法结构
  • b.运算重载符不可以改变操作数的个数
  • c.运算重载符不可以改变优先级
  • d.运算重载符不可以改变结合性

7.重载、覆盖、隐藏(重定义)的区别:

  • 重载:指的是函数具有的不同的参数列表,而函数名相同的函数。重载要求参数列表必须不同,比如参数的类型不同、参数的个数不同、参数的顺序不同。如果仅仅是函数的返回值不同是没办法重载的,因为重载要求参数列表必须不同。(发生在同一个类里)
  • 覆盖:存在类中,子类重写从基类继承过来的函数。被重写的函数不能是static的。必须是virtual的。但是函数名、返回值、参数列表都必须和基类相同。(发生在基类和子类)
  • 隐藏:子类重新定义父类中有相同名称的非虚函数(参数列表可以不同)。(发生在基类和子类)

C++中的运算符重载相关推荐

  1. C++中的运算符重载基础

    1.C++中的运算符重载基础 所谓重载,就是赋予新的含义.函数重载(Function Overloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作.运算符重载(Operator Ov ...

  2. 第十三周项目一-分数类中的运算符重载

    /**Copyright(c)2016,烟台大学计算机与控制工程学院*All rights reserved*文件名称:123.cpp*作 者:王蕊*完成日期:2016年5月25日*版 本 号:v1. ...

  3. 第十二周项目二-Time类中的运算符重载

    /**Copyright(c)2016,烟台大学计算机与控制工程学院*All rights reserved*文件名称:123.cpp*作 者:王蕊*完成日期:2016年5月24日*版 本 号:v1. ...

  4. 项目3-分数类中的运算符重载

    /* * Copyright (c) 2011, 烟台大学计算机学院 * All rights reserved. * 作 者:王静 * 完成日期:2013 年 5 月 5 日 * 版 本 号:v1. ...

  5. /项目3-分数类中的运算符重载

    /* * Copyright (c) 2011, 烟台大学计算机学院 * All rights reserved. * 作 者:王静 * 完成日期:2013 年 4 月 24 日 * 版 本 号:v1 ...

  6. 8-2 实现Time类中的运算符重载

    /* * 作 者: 霍雨佳 * 完成日期:2014 年4月15日 * 版 本 号:v1.0 * 问题描述:实现Time类中的运算符重载 * 样例输入: * 样例输出: * 项目要求:实现Time类中的 ...

  7. 实现复数类中的运算符重载(含有double类型)

    /* * 作 者: 霍雨佳 * 完成日期:2014 年4月15日 * 版 本 号:v1.0 * 问题描述:实现复数类中的运算符重载. * 样例输入: * 样例输出: * 问题分析:一个定义完整的类,是 ...

  8. 8-3 实现分数类中的运算符重载

    /* * 作 者: 霍雨佳 * 完成日期:2014 年4月15日 * 版 本 号:v1.0 * 问题描述:实现分数类中的运算符重载 * 样例输入: * 样例输出: * 项目要求:实现分数类中的运算符重 ...

  9. 第十二周上机实践项目 项目1-实现复数类中的运算符重载 (2)

    问题及代码: [项目-实现复数类中的运算符重载] (1)请用类的成员函数,定义复数类重载运算符+.-.*./,使之能用于复数的加减乘除 class Complex { public:Complex() ...

  10. 栈内存 ,堆内存区别 C++ 动态内存 == 与equal区别 复合函数奇偶性 三角函数转换公式: 虚函数和纯虚函数: C++ 中的运算符重载 数据封装,数据抽象 C++ 接口(抽象类

    目录 栈内存 ,堆内存区别 C++ 动态内存 == 与equal区别 复合函数奇偶性 三角函数转换公式: 虚函数和纯虚函数: C++ 中的运算符重载 数据封装,数据抽象 C++ 接口(抽象类): #和 ...

最新文章

  1. C# 获取当前屏幕DPI
  2. [转]代码分析工具FxCop1.36之一:介绍与使用
  3. php3d按钮,CSS实现3D按钮效果
  4. 2005年中国之“至理名言”
  5. 登陆用友服务器超时未响应,用友T3软件10.8plus1普及版服务器提示“客户端已经较长时间未连接加密服务器,超时2880秒,请退出产品重新登录”?-用友T3...
  6. ping(团队作业)
  7. 下拉菜单(含有阻止事件冒泡)
  8. 右键菜单_右键菜单太长会导致电脑卡顿?轻松删除右键菜单无用项
  9. mysql 5乱码_MySQL 5.x乱码问题解决
  10. Vue+ElementUI搭建一个后台管理框架
  11. 用c++实现一个插入,删除和随机访问都是O(1)的容器(剑指||30)
  12. 高等代数第3版下 [丘维声 著] 2015年版_黄哥友情提示:学习线性代数的书和视频...
  13. 软件工程需求分析模板(简单)
  14. 库卡 KUKA 机器人仿真软件sim pro 教程
  15. oracle报内存不足,oracle 内存不足处理
  16. 计算多项式的值编程c语言,Newton插值多项式计算函数的近似值
  17. 跟我学Kafka:Kafka消费组运维详解
  18. React——Components
  19. TensorFlow TFRecords简介
  20. 开源OA搭建教程:腾讯企业邮件接入O2平台

热门文章

  1. JavaWeb学习笔记(十)--HttpServletRequest
  2. Groovy中的闭包
  3. 把Windows CA根证书安装到iPhone
  4. 使用Process Explorer查看托管进程的性能记数器
  5. 公司数据部培训讲义:ArcMap数字化培训教程
  6. Leangoo敏捷项目管理软件 6.3.2
  7. 彻底搞懂Nginx的五大应用场景
  8. 网关技术选型,为什么选择 Openresty ?事件驱动、协程...
  9. 调研字节码插桩技术,用于系统监控设计和实现
  10. 从谷歌辞职后,作为独立开发者的第三年,我从年入 3 万做到了年入 40 万