• C++重载操作符



    操作符重载

    包括 +,-,/,% 等在内的(二元)操作符本质上是函数。调用这种“函数”时,要以不同的语法列出实参。操作符函数的实参要在操作符前后列出;普通函数的实参则在函数名之后的圆括号中列出。操作符函数的定义与普通函数相似,只是要在操作符之前附加保留字 operator。可为类类型重载预定义操作符(比如+),为这些操作符赋予新含义。

    虽然并非必须,但操作符可作为类的友元。下面的示例代码展示如何将操作符 +,==重载为友元。

    #include 
    
    using namespace std;
    
    class Example
    {
    public:
        friend Example operator +(const Example& ex1, const Example& ex2);
        friend bool operator ==(const Example& ex1, const Example& ex2);
    
        int get_a();
        int get_b();
    
        Example(int _a, int _b);
        Example();
    
    private:
        int a,b;
    };
    int main()
    {
        Example ex1(1, 2), ex2(3, 4);
        Example ex3 = ex1 + ex2;
        cout<<ex3.get_a()<<" "<<ex3.get_b()<<endl; // 4 6
        if(ex1 == ex2)
            cout<<"ex1 is equal to ex2"<<endl;
        else
            cout<<"ex1 is not equal to ex2"<<endl;
        return 0;
    }
    
    Example operator + (const Example& ex1, const Example& ex2)
    {
        Example res;
        res.a = ex1.a + ex2.a;
        res.b = ex1.b + ex2.b;
        return res;
    }
    
    bool operator == (const Example& ex1, const Example& ex2)
    {
        if(ex1.a == ex2.a && ex1.b == ex2.b)
            return true;
        else
            return false;
    }
    
    Example::Example() : a(0), b(0)
    {
    
    }
    
    Example::Example(int _a, int _b) : a(_a), b(_b)
    {
    
    }
    
    int Example::get_a()
    {
        return a;
    }
    
    int Example::get_b()
    {
        return b;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    大多数(但并非全部)操作符都可重载。操作符不一定是类的友元,但一般情况下都希望如此。具体的操作符重载规则如下:

    • 重载操作符时,至少一个实参必须是类类型。
    • 重载的操作符可以是(但不一定是)类的友元;操作符函数可以是类的成员,也可以是普通(非友元)函数。
    • 不能新建操作符。只能重载现有操作符,比如 +,-,*,/,% 等。
    • 不能改变操作符获取的实参数量。例如,重载 % 时,不能把它从二元操作符变成一元操作符;重载 ++ 时,不能把它从一元操作符变成二元操作符。
    • 不能改变操作符的优先级。重载的操作符具有和原始版本一样的优先级。例如,x * y + z 总是表示 (x * y) + z,即使 xyz 是对象,而且操作符 +* 已针对相应的类进行了重载。
    • 以下操作符不可重载:圆点操作符(.)、作用域解析操作符(::)以及.*?

    这里需要重点说明的是,将操作符函数作为类的成员与友元函数的区别。下面以操作符函数作为类的成员重现上面的示例代码:

    #include 
    
    using namespace std;
    
    class Example
    {
    public:
        Example operator +(const Example& ex2);
        bool operator ==(const Example& ex2);
    
        int get_a();
        int get_b();
    
        Example(int _a, int _b);
        Example();
    
    private:
        int a,b;
    };
    int main()
    {
        Example ex1(1, 2), ex2(3, 4);
        Example ex3 = ex1 + ex2;
        cout<<ex3.get_a()<<" "<<ex3.get_b()<<endl; // 4 6
        if(ex1 == ex2)
            cout<<"ex1 is equal to ex2"<<endl;
        else
            cout<<"ex1 is not equal to ex2"<<endl;
        return 0;
    }
    
    Example Example::operator + (const Example& ex2)
    {
        Example res;
        res.a = a + ex2.a;
        res.b = b + ex2.b;
        return res;
    }
    
    bool Example::operator == (const Example& ex2)
    {
        if(a == ex2.a && b == ex2.b)
            return true;
        else
            return false;
    }
    
    Example::Example() : a(0), b(0)
    {
    
    }
    
    Example::Example(int _a, int _b) : a(_a), b(_b)
    {
    
    }
    
    int Example::get_a()
    {
        return a;
    }
    
    int Example::get_b()
    {
        return b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    作为类的成员,函数声明定义时就只需要包含一个参数即可,ex1+ex2 相当于 ex1 作为对象调用其成员函数 + 获取参数 ex2。因为是类的成员,所以其函数定义时,获取 ex1.a 就直接使用 a 就可以。

    除了写法上的区别,作为类的成员,其只能位于第一个参数的位置(作为调用对象),比如下面的一个例子。无论是作为类的成员还是友元函数都是合法的。

    Example ex1(2,1), ex2;
    ex2 = ex1 + 20;
    
    • 1
    • 2

    而下面的例子,如果作为类的成员就是不合法的,而作为友元函数则合法。

    Example ex1(2,1), ex2;
    ex2 = 20 + ex1;
    
    • 1
    • 2

    用于自动类型转换的构造函数

    如果类定义包含了恰当的构造函数,系统会自动执行特定的类型转换。例如下面的示例:

    Example ex1(2,1), ex2;
    ex2 = ex1 + 20;
    
    • 1
    • 2

    代码看起来简单和自然,但存在一个问题,就是我们之前的代码没有重载对象与整型之间的 + 操作,而只是重载了对象之间的 + 操作。

    有两个方法解决这个问题,一个很单纯地方法就是重载一个对象与整型之间的 + 操作,另一个方法就是利用构造函数。我们可以按照下面的方式定义一个获取一个整型的构造函数。

    Example(int _a) : a(_a), b(0) {}
    
    • 1

    这样代码在发现没有进行对象和整型之间的 + 重载,会自动执行这个构造函数,生成一个匿名对象。


    重载一元操作符

    当然除了重载二元操作符(+,-,==等),还可以重载一元操作符,比如求反操作符 -,递增操作符 ++,递减操作符 -- 等。下面用代码简单说明如何重载求反操作符。

    #include 
    
    using namespace std;
    
    class Example
    {
    public:
    //    friend Example operator +(const Example& ex1, const Example& ex2);
    //    friend bool operator ==(const Example& ex1, const Example& ex2);
    
        Example operator +(const Example& ex2);
        bool operator ==(const Example& ex2);
    
        friend Example operator -(const Example& ex);
    
        int get_a();
        int get_b();
    
        Example(int _a, int _b);
        Example();
    
    private:
        int a,b;
    };
    int main()
    {
        Example ex1(1, 2), ex2(3, 4);
        Example ex3 = ex1 + ex2;
        cout<<ex3.get_a()<<" "<<ex3.get_b()<<endl; // 4 6
        if(ex1 == ex2)
            cout<<"ex1 is equal to ex2"<<endl;
        else
            cout<<"ex1 is not equal to ex2"<<endl;
        Example ex4 = -ex1;
        cout<<"ex4 is opposite to ex1, it is "<<ex4.get_a()<<" "<<ex4.get_b()<<endl; // -1 -2
        return 0;
    }
    
    Example Example::operator + (const Example& ex2)
    {
        Example res;
        res.a = a + ex2.a;
        res.b = b + ex2.b;
        return res;
    }
    
    bool Example::operator == (const Example& ex2)
    {
        if(a == ex2.a && b == ex2.b)
            return true;
        else
            return false;
    }
    
    Example operator - (const Example& ex)
    {
        Example res;
        res.a = -ex.a;
        res.b = -ex.b;
        return res;
    }
    
    Example::Example() : a(0), b(0)
    {
    
    }
    
    Example::Example(int _a, int _b) : a(_a), b(_b)
    {
    
    }
    
    int Example::get_a()
    {
        return a;
    }
    
    int Example::get_b()
    {
        return b;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    重载>>和<<

    cout 使用的插入操作符 << 是二元操作符。例如以下语句:

    cout << "Hello out there.\n" ;
    
    • 1

    操作符是 <<,第一个操作数是输出流 cout,第二个则是字符串值 "Hello out there.\n"。这两个操作数都可以改变。如 foutofstream 类型的输出流,而且已通过 open 调用与一个文件连接,就可将 cout 替换成 fout,字符串会写到与 fout 连接的文件中。当然,还可以将字符串 "Hello out there.\n" 替换成其他字符串、变量或数字。由于 << 是操作符,所以应该能像重载 +- 等操作符那样重载 <<,但是需要注意更多细节。

    1. 返回值必须是流。
    2. 返回值类型名称后必须添加符号 &
    // 函数声明
    class ClassName
    {
    public:
    	friend istream& operator >>(istream& Parameter_1,
    								ClassName& Parameter_2);
    	friend ostream& operator <<(ostream& Parameter_3,
    								const ClassName& Parameter_4);
    
    // 定义
    istream& operator >>(istream& Parameter_1,
    					 ClassName& Parameter_2)
    {
    
    }
    ostream& operator <<(ostream& Parameter_3,
    					const ClassName& Parameter_4)
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    HTML网页设计结课作业 web课程设计网页规划与设计 网页设计成品DW静态网页 Web大学生网页成品 web网页设计期末课程大作业
    如何使用gpt提高效率
    【STC8A8K64D4开发板】第2-8讲:片内存储器
    java版工程管理系统Spring Cloud+Spring Boot+Mybatis实现工程管理系统源码
    PowerBI开发:用自然语言来探索数据--Q&A
    游戏开发者应该了解的小游戏变现逻辑
    C#毕业设计——基于MD5+RSA的数字签名设计与实现(毕业论文+程序源码)——数字签名系统
    Haddop访问不了loaclhost9870
    RK3399 Android7.1修改安兔兔等第三方软件读到的内核版本信息
    433-C++基础语法(51-60)
  • 原文地址:https://blog.csdn.net/weixin_44491423/article/details/126049257