• C++学习笔记之运算符重载


    一、运算符重载基本知识

    在前面的一篇博文

    C++学习笔记之模板(1)——从函数重载到函数模板

    中,介绍了函数重载的概念,定义及用法,函数重载(也被称之为函数多态)就是使用户能够定义多个名称相同但特征标(参数列表)不同的函数,目的是在对不同类型的参数执行相同的操作时只用一个同名的函数。

    运算符重载,就是使同一个运算符在面临不同类型的数据时作出不同的操作(函数重载是操作相同),就是让同一个运算符有多重功能。实际上我们经常用的许多运算符已被重载,例如,将*用于地址,将得到存储在这个地址中的值;但将它用于两个数字时,得到的将是它们的乘积。

    C++允许将运算符重载扩展到用户定义的类型,如允许使用+将两个对象相加,编译器根据操作的数目和类型决定使用哪种加法的定义。

    运算符重载格式如下:

    operator运算符();

    例如,operator+()重载+运算符,operator-()重载-运算符等。但是被重载的运算符必须是有效的C++运算符,不能自创一个新的符号。

    二、运算符重载示例

    假设写一篇博客,上午花了1小时42分钟编码,下午又花了2小时33分钟修改,要计算总共花的时间,很显然与加法概念很吻合,但是要相加的单位是小时与分钟的混合,与内置的加法类型不匹配。采用一个使用方法来处理加法的Time类。作为对比,首先使用常规方法,建立一个名为sum()的函数,然后介绍使用重载运算符。

    函数的方法:

     1 //mytime0,未使用运算符重载
     2 #ifndef MYTIME0_H
     3 #define MYTIME0_H
     4 
     5 class Time
     6 {
     7 private:
     8     int hours;
     9     int minutes;
    10 public:
    11     Time();
    12     Time(int h, int m = 0);
    13     void addMin(int m);
    14     void addHr(int h);
    15     void reset(int h = 0, int m = 0);
    16     Time sum(const Time & t ) const;
    17     void show() const;
    18 };
    19 
    20 #endif
     1 #include <iostream>
     2 #include "mytime0.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::addMin(int m)
    16 {
    17     minutes += m;
    18     hours += minutes / 60;
    19     minutes %= 60;
    20 }
    21 
    22 void Time::addHr(int h)
    23 {
    24     hours += h;
    25 }
    26 
    27 void Time::reset(int h, int m)
    28 {
    29     hours = h;
    30     minutes = m;
    31 }
    32 
    33 Time Time::sum(const Time & t) const
    34 {
    35     Time result;
    36     result.minutes = minutes + t.minutes;
    37     result.hours = hours + t.hours +result.minutes / 60;
    38     result.minutes %= 60;
    39     return result;
    40 }
    41 
    42 void Time::show() const
    43 {
    44     std::cout << hours << " hours, "    << minutes << " minutes";
    45 }

     

     1 /*usetime0*/
     2 #include <iostream>
     3 #include "mytime0.h"
     4 
     5 int main()
     6 {
     7     using std::cout;
     8     using std::endl;
     9     Time planning;
    10     Time coding(1, 42);
    11     Time fixing(2, 33);
    12     Time total;
    13 
    14     cout << "planning time = ";
    15     planning.show();
    16     cout << endl;
    17 
    18     cout << "coding time = ";
    19     coding.show();
    20     cout << endl;
    21 
    22     cout << "fixing time = ";
    23     fixing.show();
    24     cout << endl;
    25 
    26     total = coding.sum(fixing);
    27     cout << "coding.sum(fixing) = ";
    28     total.show();
    29     cout << endl;
    30 
    31     return 0;
    32 }

    运行结果:

     

     运算符重载的方法:

    这里所举例子比较简答,我们只需要将sum()名称改为operator+()即可。程序清单如下:

     1 //mytime0,未使用运算符重载
     2 #ifndef MYTIME0_H
     3 #define MYTIME0_H
     4 
     5 class Time
     6 {
     7 private:
     8     int hours;
     9     int minutes;
    10 public:
    11     Time();
    12     Time(int h, int m = 0);
    13     void addMin(int m);
    14     void addHr(int h);
    15     void reset(int h = 0, int m = 0);
    16     Time operator+(const Time & t ) const; 
    17     void show() const;
    18 };
    19 
    20 #endif

     

     1 #include <iostream>
     2 #include "mytime0.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::addMin(int m)
    16 {
    17     minutes += m;
    18     hours += minutes / 60;
    19     minutes %= 60;
    20 }
    21 
    22 void Time::addHr(int h)
    23 {
    24     hours += h;
    25 }
    26 
    27 void Time::reset(int h, int m)
    28 {
    29     hours = h;
    30     minutes = m;
    31 }
    32 
    33 Time Time::operator+(const Time & t) const
    34 {
    35     Time result;
    36     result.minutes = minutes + t.minutes;
    37     result.hours = hours + t.hours +result.minutes / 60;
    38     result.minutes %= 60;
    39     return result;
    40 }
    41 
    42 void Time::show() const
    43 {
    44     std::cout << hours << " hours, "    << minutes << " minutes";
    45 }
     1 /*usetime0*/
     2 #include <iostream>
     3 #include "mytime0.h"
     4 
     5 int main()
     6 {
     7     using std::cout;
     8     using std::endl;
     9     Time planning;
    10     Time coding(1, 42);
    11     Time fixing(2, 33);
    12     Time total;
    13 
    14     cout << "planning time = ";
    15     planning.show();
    16     cout << endl;
    17 
    18     cout << "coding time = ";
    19     coding.show();
    20     cout << endl;
    21 
    22     cout << "fixing time = ";
    23     fixing.show();
    24     cout << endl;
    25 
    26     total = coding + fixing; //通过运算符+号直接调用重载的运算符
    27     cout << "coding + fixing =  ";
    28     total.show();
    29     cout << endl;
    30 
    31     Time morefixing(2, 42);
    32     cout << "morefixing time = ";
    33     morefixing.show();
    34     cout << endl;
    35 
    36     total = morefixing.operator+(total);//也可以通过函数名的方式调用
    37     cout << "morefixing.operator+(total) = ";
    38     total.show();
    39     cout << endl;
    40 
    41     return 0;
    42 }

    总之,operator+()函数名使得可以使用函数表示法或运算符表示法来调用它。

    如果t1,t2,t3,t4都是Time对象,可以这样操作吗:

     t4 = t1 + t2 +t3;

    我们来仔细分析下,+是从左向右结合的运算符,根据上述代码中的函数,上述语句首先被转换为:

    t4 = t1.operator+(t2 + t3);  //t1调用operator+()函数

    接着继续转换为:

    t4 = t1.operator+(t2.operator+(t3)); //t2调用operator+()函数

    上述语句合法吗?当然合法,因为 t2.operator+(t3)返回一个Time对象,是t2和t3的和,该对象又成为函数调用t1.operator+()的参数,该调用返回t1与表示t2和t3之和的Time对象的和。最后返回值为t1,t2,t3之和,正是我们想要的结果。可以看出,运算符重载实现运算功能要比函数看起来更加自然一些。

    三、重载的限制

    多数C++运算符都可以用这样的方式重载。但是没有绝对的自由。主要限制有如下几条:

    1. 重载后的运算符至少有一个操作数是用户定义的类型。这将防止用户为标准类型重载运算符。假如没有这个限制,我们可以将-重载为两个double相加,而不是它们的差,就乱套了。
    2. 使用运算符不能违反运算符原来的句法规则。例如。不能将求模运算符(%)重载成使用一个操作数:% x.同时不能修改运算符的优先级。
    3. 不能创建新的运算符。例如,不能定义operator**()函数来表示求幂。
    4. 不能重载如下运算符:                                                                                                                                                                                                                                      
      • sizeof  sizeof运算符
      • .  成员运算符
      • .* 成员指针运算符
      • :: 作用域解析运算符
      • ?: 条件运算符
      • typeid 一个RTTI运算符
      • const_cast
      • dynamic_cast
      • reinterpret_cast
      • static_cast

      5. 大多数运算符都可以通过成员或者非成员函数重载,但是下面的运算符只能通过成员函数重载

        = 赋值运算符

        () 函数调用运算符

        [] 下表运算符

        -> 通过指针访问类成员的运算符。

  • 相关阅读:
    python常用包收集
    python pep 8
    常用python字符串处理
    安全资源整理
    WordPress下载安装简单配置实例
    PHP框架学习之Laravel基本功能
    PHP框架学习之Laravel安装
    PHP面试题之优化
    PHP面试题之小杂鱼
    PHP面试题之文件目录操作
  • 原文地址:https://www.cnblogs.com/90zeng/p/Cpp_operator_overloading.html
Copyright © 2020-2023  润新知