zoukankan      html  css  js  c++  java
  • C++解析(17):操作符重载

    0.目录

    1.操作符重载

    2.完善的复数类

    3.小结

    1.操作符重载

    下面的复数解决方案是否可行?

    示例1——原有的解决方案:

    #include <stdio.h>
    
    class Complex 
    {
        int a;
        int b;
    public:
        Complex(int a = 0, int b = 0)
        {
            this->a = a;
            this->b = b;
        }
        
        int getA() { return a; }
        
        int getB() { return b; }
        
        friend Complex Add(const Complex& p1, const Complex& p2);
    };
    
    Complex Add(const Complex& p1, const Complex& p2)
    {
        Complex ret;
        
        ret.a = p1.a + p2.a;
        ret.b = p1.b + p2.b;
        
        return ret;
    }
    
    int main()
    {
        Complex c1(1, 2);
        Complex c2(3, 4);
        Complex c3 = Add(c1, c2); // c1 + c2
        
        printf("c3.a = %d, c3.b = %d
    ", c3.getA(), c3.getB());
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    c3.a = 4, c3.b = 6
    

    操作符重载:

    • C++中的重载能够扩展操作符的功能
    • 操作符的重载以函数的方式进行
    • 本质——用特殊形式的函数扩展操作符的功能

    通过operator关键字可以定义特殊的函数
    operator的本质是通过函数重载操作符
    语法:

    示例2——使用操作符重载函数代替原有函数:

    #include <stdio.h>
    
    class Complex 
    {
        int a;
        int b;
    public:
        Complex(int a = 0, int b = 0)
        {
            this->a = a;
            this->b = b;
        }
        
        int getA() { return a; }
        
        int getB() { return b; }
        
        friend Complex operator + (const Complex& p1, const Complex& p2);
    };
    
    Complex operator + (const Complex& p1, const Complex& p2)
    {
        Complex ret;
        
        ret.a = p1.a + p2.a;
        ret.b = p1.b + p2.b;
        
        return ret;
    }
    
    int main()
    {
        Complex c1(1, 2);
        Complex c2(3, 4);
        Complex c3 = operator + (c1, c2); // c1 + c2
        
        printf("c3.a = %d, c3.b = %d
    ", c3.getA(), c3.getB());
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    c3.a = 4, c3.b = 6
    

    可以将操作符重载函数定义为类的成员函数

    • 比全局操作符重载函数少一个参数左操作符
    • 不需要依赖友元就可以完成操作符重载
    • 编译器优先在成员函数中寻找操作符重载函数

    示例3——不使用友元,而是使用类的成员函数(编译器优先在成员函数中寻找操作符重载函数):

    #include <stdio.h>
    
    class Complex 
    {
        int a;
        int b;
    public:
        Complex(int a = 0, int b = 0)
        {
            this->a = a;
            this->b = b;
        }
        
        int getA() { return a; }
        
        int getB() { return b; }
        
        Complex operator + (const Complex& p)
        {
            Complex ret;
            printf("Complex operator + (const Complex& p)
    ");
            ret.a = this->a + p.a;
            ret.b = this->b + p.b;
            
            return ret;
        }
        
        friend Complex operator + (const Complex& p1, const Complex& p2);
    };
    
    Complex operator + (const Complex& p1, const Complex& p2)
    {
        Complex ret;
        printf("Complex operator + (const Complex& p1, const Complex& p2)
    ");
        ret.a = p1.a + p2.a;
        ret.b = p1.b + p2.b;
        
        return ret;
    }
    
    int main()
    {
        Complex c1(1, 2);
        Complex c2(3, 4);
        Complex c3 = c1 + c2; // c1.operator + (c2)
        
        printf("c3.a = %d, c3.b = %d
    ", c3.getA(), c3.getB());
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    Complex operator + (const Complex& p)
    c3.a = 4, c3.b = 6
    

    2.完善的复数类

    复数类应该具有的操作:

    利用操作符重载

    • 统一复数实数运算方式
    • 统一复数实数比较方式

    先实现Complex.h头文件:

    // Complex.h
    #ifndef _COMPLEX_H_
    #define _COMPLEX_H_
    
    class Complex
    {
        double a;
        double b;
    public:
        Complex(double a = 0, double b = 0);
        double getA();
        double getB();
        double getModulus();
        
        Complex operator + (const Complex& c);
        Complex operator - (const Complex& c);
        Complex operator * (const Complex& c);
        Complex operator / (const Complex& c);
        
        bool operator == (const Complex& c);
        bool operator != (const Complex& c);
        
        Complex& operator = (const Complex& c);
    };
    
    #endif
    

    再实现Complex.cpp具体操作:

    // Complex.cpp
    #include "Complex.h"
    #include "math.h"
    
    Complex::Complex(double a, double b)
    {
        this->a = a;
        this->b = b;
    }
    
    double Complex::getA()
    {
        return a;
    }
    
    double Complex::getB()
    {
        return b;
    }
    
    double Complex::getModulus()
    {
        return sqrt(a * a + b * b);
    }
    
    Complex Complex::operator + (const Complex& c)
    {
        double na = a + c.a;
        double nb = b + c.b;
        Complex ret(na, nb);
        
        return ret;
    }
    
    Complex Complex::operator - (const Complex& c)
    {
        double na = a - c.a;
        double nb = b - c.b;
        Complex ret(na, nb);
        
        return ret;
    }
    
    Complex Complex::operator * (const Complex& c)
    {
        double na = a * c.a - b * c.b;
        double nb = a * c.b + b * c.a;
        Complex ret(na, nb);
        
        return ret;
    }
    
    Complex Complex::operator / (const Complex& c)
    {
        double cm = c.a * c.a + c.b * c.b;
        double na = (a * c.a + b * c.b) / cm;
        double nb = (b * c.a - a * c.b) / cm;
        Complex ret(na, nb);
        
        return ret;
    }
        
    bool Complex::operator == (const Complex& c)
    {
        return (a == c.a) && (b == c.b);
    }
    
    bool Complex::operator != (const Complex& c)
    {
        return !(*this == c);
    }
        
    Complex& Complex::operator = (const Complex& c)
    {
        if( this != &c )
        {
            a = c.a;
            b = c.b;
        }
        
        return *this;
    }
    

    最后实现main函数:

    // test.cpp
    #include <stdio.h>
    #include "Complex.h"
    
    int main()
    {
        Complex c1(1, 2);
        Complex c2(3, 6);
        Complex c3 = c2 - c1;
        Complex c4 = c1 * c3;
        Complex c5 = c2 / c1;
        
        printf("c3.a = %f, c3.b = %f
    ", c3.getA(), c3.getB());
        printf("c4.a = %f, c4.b = %f
    ", c4.getA(), c4.getB());
        printf("c5.a = %f, c5.b = %f
    ", c5.getA(), c5.getB());
        
        Complex c6(2, 4);
        
        printf("c3 == c6 : %d
    ", c3 == c6);
        printf("c3 != c4 : %d
    ", c3 != c4);
        
        (c3 = c2) = c1;
        
        printf("c1.a = %f, c1.b = %f
    ", c1.getA(), c1.getB());
        printf("c2.a = %f, c2.b = %f
    ", c2.getA(), c2.getB());
        printf("c3.a = %f, c3.b = %f
    ", c3.getA(), c3.getB());
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp Complex.cpp
    [root@bogon Desktop]# ./a.out 
    c3.a = 2.000000, c3.b = 4.000000
    c4.a = -6.000000, c4.b = 8.000000
    c5.a = 3.000000, c5.b = 0.000000
    c3 == c6 : 1
    c3 != c4 : 1
    c1.a = 1.000000, c1.b = 2.000000
    c2.a = 3.000000, c2.b = 6.000000
    c3.a = 1.000000, c3.b = 2.000000
    

    注意事项:

    • C++规定赋值操作符(=)只能重载为成员函数
    • 操作符重载不能改变原操作符的优先级
    • 操作符重载不能改变操作符的个数
    • 操作符重载不应改变操作符的原有语义

    3.小结

    • 操作符重载是C++的强大特性之一
    • 操作符重载的本质通过函数扩展操作符的功能
    • operator关键字是实现操作符重载的关键
    • 操作符重载遵循相同的函数重载规则
    • 全局函数成员函数都可以实现对操作符的重载
    • 复数的概念可以通过自定义类实现
    • 复数中的运算操作可以通过操作符重载实现
    • 赋值操作符只能通过成员函数实现
    • 操作符重载的本质为函数定义
  • 相关阅读:
    【转】【C++】【MFC】各种数据类型大小
    【转】【C++】【MFC】关于RADIO BUTTON的使用方法
    【C++】【MFC】创建新的线程函数
    【C++】【MFC】定义全局变量的方法
    【Quartus错误】Internal Error: Sub-system: AMERGE
    【转/TCP协议编程】 基于TCP的Socket 编程
    SQL递归查询(with as)
    SQL查询月、天、周、年(MySql的实例对比)
    sql 基础语句
    经典SQL语句大全
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10084115.html
Copyright © 2011-2022 走看看