美文网首页
C++ 操作符重载

C++ 操作符重载

作者: 我阿郑 | 来源:发表于2021-12-24 12:05 被阅读0次
    • 重载算数操作符
    • 重载操作符[]
    • 重载关系操作符
    • 重载类型转换操作符
    • 重载输入输出操作符

    引例

    用一个类Fraction,用于表示2/3, 87/890这种分数

    class Fraction
    {
    public:
         Fraction(int n ,int d): num(n), den(d)
         {
         }
         int num; // 分子
         int den; // 分母
    };
    
    // 定义两个数
    Fraction fa(2,3); // 2/3
    Fraction fb(3,5); // 3/5 
    

    按理来说,两个数是可以进行算术运算的 例如:

    int a = 2;
    int b = 3;
    int c = a + b;
    

    对于我们自定义的Fraction这种类型,默认情况下是不支持算术运算的,我们希望它也能够支持加减乘除的算术运算

    // 希望可以达到这种效果
    Fraction fc = fa + fb;
    

    一、重载算术运算符

    使用重载运算符的语法,可以使得自己定义的类支持加减乘除等算术运算符

    • 第一种方式: 类操作符
    // 重载加号操作符
    Fraction operator + (const Fraction& other)
    {
        Fraction result;
        // 本对象和other运算,得出结果并返回
        return result;
    }
    // 在 fc = fa + fb 语句中,operator+被调用
    

    注意:
    (1)重载操作符的形式上像一个函数,但它不是函数
    (2)名称:operator + ,这个是固定不变的
    (3)返回值:类型不变,总是为该对象的类型
    (4)参数:基本上也不变
    (5)受public/protected/private的限制

    • 另一种写法:重载全局操作符
    // 重载全局操作符
    Fraction operator + (const Fraction& a, const Fraction& b)
    {
        Fraction result;
        result.den = a.den * b.den; 
        result.num = a.num * b.den + a.den * b.num;     return result;
    }
    

    通常,要将全局操作符的重载声明为类的朋友
    num/den为private的时候,必须将此重载的操作符声明为friend

    注意

    (1)当类操作符和全局操作符同时被重载时,类操作符被优先调用 (就近原则)
    (2)各种重载操作符,其形式基本是固定的。(名称、参数、返回值,基本上都是固定写法)给出加号(+)的示例。其他的操作符(-, * , / ) 也是一样的
    (3)通常,要将全局操作符的重载声明为类的朋友

    举例

    实现两个Point相加,即

    Point p1(10,20);
    Point p2(20,30);
    Point p = p1 + p2;
    

    代码如下:

    class Point{
        friend Point operator+ (const Point &, const Point &);
        int m_x;
        int m_y;
    public:
        Point(int x, int y):m_x(x), m_y(y) {}
        void display() {
            cout << "(" << m_x << "," << m_y << ")" << endl;
        }
        // 拷贝构造
        Point(const Point &point) {
            m_x = point.m_x;
            m_y = point.m_y;
        }
    }
    
    // 重载全局操作符
    Point operator+(const Point &p1, const Point &p2) {
        return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
    }
    

    既然我们是实现Point的运算符重载,所以最好还是将运算符重载的操作放在Point类内部,不用写成全局函数的好

    二、重载操作符[]

    [] 用于访问一组元素中的一个元素,默认地,数组是支持下标访问的。

    int a[5] = {1,2,3,4,5};
    a[0] = 111; // 写操作
    int b = a[0]; // 读操作
    

    []中的下标称为:索引,其作用是用来唯一的标识一个元素

    什么时候要重载 [ ]

    一个对象设计用于包含多个元素时,可以重载操作符[]

    比如:一个字符串Text,它包含了多个元素(每个元素是一个字符)

    Text txt("hello world");
    char ch = txt[0]; // 'h'
    

    比如:在一个DataStore里存储多个Student数据

    DataStore ds;
    Student&  st = ds["shaofa"]; // 查找姓名为"shaofa"的记录
    

    重载操作符的一般形式

    Element&  operator [] (Type index)
    {
    }
    

    其中:
    名字: operator[],是固定不变的
    返回值:一般应该返回一个子元素的引用,表示返回值是一个“左值”,可读可写
    参数:类型可以自己选择,用于指定元素的下标。不一定非要使用int,使用其他类型也可以。

    示例

    Text类用于存储一串文本

    char& operator[] (int index)
    {
        return m_buf[index];
    }
    

    注意

    (1) 操作符[]的返回值类型为引用,才算是符合使用惯例。
    (即:应该返回一个左值

    (2) 元素下标的类型是不一定要用int,用char*也可以

    (3) 操作符[]是可以重载的,参数类型不同

    (4) 必须考虑元素不存在的情形

    三、重载关系操作符

    关系操作符: <, <=, >, >=, ==, !=

    默认地,编译器不支持对自定义的类进行关系操作。例如,我们想判断两个分数Fraction是否相等

    Fraction fa(2, 3);
    Fraction fb(4, 6);
    if(fa == fb)  // 编译器报错!不支持==
    {
    }
    

    操作符==的重载方法

    (1) 重载类操作符

    class Object
    {
    public:
        bool operator == (const Object& other){ }
    };
    

    (2) 重载全局操作符

    bool operator == (const Object& a, const Object& b )
    {}
    

    代码框架:

    class Fraction
    {
    public:
        ///////////////////////////////
        bool operator == (const Fraction& other)
        {
            return true;
        }
    
    };
    

    四、类型转换操作符

    C++中允许将一个类型转换为另一个类型

    int a = (int) 1.23;  // 将double转成int
    

    比如,现在自己定义了一个类Fraction,表示分数。
    那么怎么样才可以把Fraction类型直接转成一个double类型呢?

    重载类型转换操作符 ()

    class Object
    {
    public:
        operator Type() // Type为目标类型
        {
            Type result;
            return result;
        }
    };
    

    五、输入输出操作符

    C++中引入操作符 >> 表示输入, <<表示输出
    (注意:位操作里它们承担的意思是:左移位、右移位,这里不要混淆了)

    // 在位操作中:
    unsigned int a = 0xAA << 4; 
    (左操作数为整型时,表示移位)
    
    Logger lg;
    lg << "hello,world";
    (左操作数为自定义对象,表示输入输出)
    

    演示输出操作符 << 的用法

    // 定义一个类: Logger,用于输出打印日志
    Logger& operator << (Type value)
    {
        return *this;
    }
    
    // 定义一个对象
    Logger lg; 
    lg << 1;
    lg << 2.0;
    lg << "hello";
           
    // 或者串起来写
    lg << 1 << ", " << 2.0 << "hello" ;
    

    名称: operator <<
    返回值:左值,一般返回对象自己
    参数:待输出的数据

    说明

    1. 注意:为什么返回左值?
      因为,如果不返回左值,就没法串起来写。

    2. C++是借用了这两个操作符
      当左操作数为整数时,表示“移位”
      当为自定义类型class时,表示“输入、输出”

    相关文章

      网友评论

          本文标题:C++ 操作符重载

          本文链接:https://www.haomeiwen.com/subject/lwylqrtx.html