C++中的运算符重载

本文介绍了C++中运算符重载的概念、规则及其实例。重点讲解了如何通过重载来扩展运算符的功能,使其适用于自定义数据类型。包括友元重载、成员重载、双目运算符重载等,并探讨了赋值运算符和数组下标运算符的重载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

所谓重载,就是从新赋予新的含义的意思。运算符重载的本质是函数重载。重载函数的一般格式如下:

函数类型 operator 运算符名称(形参列表)
{
    重载实体;
}

operator 运算符 一起构成了新的函数名,例如:

const Complex operator+(const Complex &c1,  const Complex &c2);

上面这种形式我们一般只说重载了”+”运算符

二、重载规则

1、C++不允许用户自己定义新的运算符,只能对已有的C++运算啊符进行重载
2、C++允许重载的运算符

这里写图片描述

3、C++中不允许重载的运算符
作用域操作符:::
条件操作符:?:
点操作符:.
指向成员操作的指针操作符:->*,.*
预处理符号:#
4、重载不能改变运算符运算对象(即操作数)的个数

如,关系运算符“>”和“<”等是双目运算符,重载后仍为双目运算符,需要两个参数。运算符”+“,”-“,”*“,”&“等既可以作为单目运算符,也可以作为双目运算符,可以分别将它们重载为单目运算符或双目运算符

5、重载不能改变运算符的优先级别
6、重载不能改变运算符的结合性
7、重载运算符的函数不能有默认的参数
8、重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。
9、用于类对象的运算符一般必须重载,但有两个例外,运算符”=“和运算符”&“不 必用户重载
10、应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能
11、运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数

三、运算符重载实例

1、友元重载
#include <iostream>
using namespace std;

class Complex
{
    public:
        Complex(float x = 0, float y = 0) : _x(x), _y(y){}
        void dis()
        {
            cout << "(" << _x << "," << _y << ")"   << endl;
        }

        friend const Complex operator+(const Complex &c1, const Complex &c2);
    private:
        float _x;
        float _y;
};
//友元函数重载+
const Complex operator+(const Complex &c1, const Complex &c2)
{
    return Complex(c1._x + c2._x, c1._y + c2._y);   
}

int main()
{
    Complex c1(3, 4);
    Complex c2(5, 6);

    c1.dis();
    c2.dis();

    Complex c3 = c1 + c2;
    c3.dis();

    return 0;   
}

执行结果如下:
这里写图片描述

2、成员重载案例
#include <iostream>
using namespace std;

class Complex
{
    public:
        Complex(float x = 0, float y = 0) : _x(x), _y(y){}
        void dis()
        {
            cout << "(" << _x << "," << _y << ")"   << endl;
        }
        const Complex operator+(const Complex &another);
    private:
        float _x;
        float _y;
};


const Complex Complex::operator+(const Complex &another)
{
    cout << "成员函数重载" << endl;
    return Complex(this->_x + another._x, this->_y + another._y);   
}

int main()
{
    Complex c1(3, 4);
    Complex c2(5, 6);

    c1.dis();
    c2.dis();

    Complex c3 = c1 + c2;
    c3.dis();

    return 0;   
}

执行结果如下:
这里写图片描述

3、双目运算符重载
#include <iostream>
using namespace std;

class Complex
{
    public:
        Complex(float x = 0, float y = 0) : _x(x), _y(y){}

        void dis()
        {
            cout << "(" << _x << "," << _y << ")" << endl;  
        }

        Complex &operator+= (Complex &another)
        {
            cout << "调用+=操作符重载函数" << endl;
            this->_x += another._x, this->_y += another._y;
            return *this;   
        }
    private:
        float _x;
        float _y;   
};

int main()
{
    Complex a(10, 0);
    Complex b(20, 0);
    Complex c(30, 0);
    (a += b) += c;
    a.dis();
    b.dis();
    c.dis();
    return 0;   
}

这里写图片描述

4、友元还是成员
#include <iostream>
using namespace std;

class Mail;

class Sender
{
    public:
        Sender(string s) : str_addr(s){}

        Sender& operator << (const Mail & mail); //成员函数重载

    private:
        string str_addr;    
};

class Mail
{
    public:
        Mail(string _t, string _c):_title(_t),_content(_c){}
        friend Sender& Sender::operator<<(const Mail& mail); 
    private:
        string _title;
        string _content;    
};

Sender& Sender::operator << (const Mail & mail)
{
    cout << "Adress" << str_addr << endl;
    cout << "Title" << mail._title <<endl;
    cout << "Content" << mail._content << endl; 
    return *this;
}

int main()
{
    Sender sender("guoshijiang2012@163.com");
    Mail m1("note", "meeting at 2.0pm");
    Mail m2("Ok", "I will coming");
    sender << m1 << m2;
    return 0;   
}

执行结果:
这里写图片描述

结论:
  • 一个操作符的左右操作数不一定是相同类型的对象,这就涉及到将该操作符函数定义为谁的友元,谁的成员问题。
  • 一个操作符函数,被声明为哪个类的成员,取决于该函数的调用对象(通常是左操作数)。
  • 一个操作符函数,被声明为哪个类的友员,取决于该函数的参数对象(通常是右操作数)。
4、赋值运算符重载

用一个己有对象,给另外一个己有对象赋值。两个对象均己创建结束后,发
生的赋值行为。

类名
{
    类名& operator=(const 类名& 源对象) 拷⻉贝体
}

例如:

class A
{
    A& operator=(const A& another)
    {
        return *this;
    }
};
重载规则

1 系统提供默认的赋值运算符重载,一经实现,不复存在。
2 系统提供的也是等位拷贝,也就浅拷贝,一个内存泄漏,重析构。
3 要实再深深的赋值,必须自定义。
4 自定义面临的问题有三个:

  • 自赋值
  • 内存泄漏
  • 重析构。
  • 返回引用,且不能用 const 修饰。其目的是实现连等式
5、数组下标运算符 (operator[])

形式:

类型类::operator[](类型);

设 x 是类 X 的一个对象,则表达式x[y],可被解释为x.operator

6、函数调用符号 (operator () )

把类对象像函数名一样使用。仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

形式:

class 类名
{
    返值类型 operator()(参数类型) 函数体
}

案例:

#include <iostream>
using namespace std;

class Sqr
{
    public:
        int operator()(int i)
        {
            return i * i;   
        }

        double operator()(double d)
        {
            return d * d;
        }
    private:    

};

int main()
{
    Sqr sqr;
    int i = sqr(4);
    double d = sqr(5.5);
    cout<<i<<endl;
  cout<<d<<endl;
    return 0;   
}

执行结果如下:

这里写图片描述

四、总结

函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,因此,一个函数名就可以用来代表不同功能的函数,也就是”一名多用”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The_Web3_社区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值