C++速览之运算符重载

运算符重载

1、是什么?
函数可以重载, 运算符也是可以重载的。 运算符重载是对已有的运算符重新进行定义,赋予其另一种功能,以达到适应不同的数据类型。运算符重载不能改变它本来的寓意(也就是 加法不能变更为 减法)

运算符重载只是一种 “语法上的方便” , 背后实际上是一种函数调用的方式

#include<iostream>

using namespace std;

class Student{
public:
    int age;
   
    Student(int age):age(age){

    }
};

int main(){
    
    int a = 3 ;
    int b = 4 ; 

    //两个整数相加,这是允许的。
    int c = a + b ; 

    Student s1(10) ; 
    Student s2(20) ; 

    //两个学生相加,则编译失败。即使你认为两个学生的年纪之和为第三个学生的年纪
    //依然不允许通过编译,因为 + 运算符在定义之初就不认识Student这种类型。
    Student s3 = s1 + s2 ; // 编译器不通过
    
    return 0 ;
}

2、运算符重载的意义
运算符的重载实际上背后是调用对应的函数,重载运算符使得把复杂的代码包装起来,对外暴露简单的一个符号即可。实际上不使用运算符重载,也一样可以实现功能,如下面两个学生相加的示例所示:

#include<iostream>

using namespace std;

class Student {
public:
    int age;

    Student(int age) : age(age) {

    }
};

int main() {

    Student s1(10);
    Student s2(20);

    //先对两个学生的年龄做加法
    int age = s1.age + s2.age;

    //再赋值给第三名学生
    Student s3(age);

    cout << "第三名学生的年龄是: " << s3.age << endl;

    return 0;
}

3、定义运算符

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的

比如,要重载 + 运算符 ,那么可以声明一个函数为 operator+() ,函数声明的位置可以是类的内部,也可以是类的外部,所以又有了成员函数和全局函数的划分。与其他函数一样,重载运算符函数,也可以拥有返回值和参数列表。此处仍然以学生相加的案例举例。

3.1 成员函数方式
把重载的运算符函数定义在类中,此时只需要接收一个参数,因为类的对象本身作为+ 的前面调用者

#include<iostream>

using namespace std;

class Student {
public:
    int age;

    Student(int age) : age(age) {

    }

    //两个学生的年龄之和,则为第三个学生的命令,所以此处需要返回一个学生对象。
    //好方便在外面接收。
    Student operator+(Student &s) {
        Student temp(this->age + s.age);
        return temp;
    }

};

int main() {

    Student s1(10);
    Student s2(20);

    //这里等于使用s1的对象,调用了operator+这个函数, +后面的 s2 则被当成参数来传递
    Student s3 = s1 + s2;

    cout << "s3.age = " << s3.age << endl;

    return 0;
}

3.2 全局函数方式
并不是所有的运算符重载都能定义在类中,比如,需要扩展一些已有的类,对它进行运算符重载,而这些类已经被打成了一个库来使用,此时通过全局函数的方式来实现运算符重载

#include<iostream>

using namespace std;

class Student {
public:
    int age;

    Student(int age) : age(age) {

    }
};

//由于函数并非定义在类中,所以此处无法使用到this指针,则需要传递两个对象进来。
Student operator+(Student &s, Student &ss) {
    Student temp(s.age + ss.age);
    return temp;
}

int main() {

    Student s1(20);
    Student s2(30);

    //这里等于使用s1的对象,调用了operator+这个函数, +后面的 s2 则被当成参数来传递
    Student s3 = s1 + s2;

    cout << "s3.age = " << s3.age << endl;
    return 0;
}

4、赋值运算符重载
赋值运算符在此前编码就见过了,其实就是 = 操作符

#include <iostream>

using namespace std;


class Student {
public:
    int no;
    int age;

    // 构造函数
    Student(int no, int age) {
        cout << this << "构造函数被执行...\n";
        this->no = no;
        this->age = age;
    }

    // 拷贝构造
    Student(const Student &stu) {
        this->no = stu.no;
        this->age = stu.age;
        cout << this << "拷贝构造函数被执行...\n";
    }

    // 拷贝赋值
    Student &operator=(const Student &stu) {
        cout << this << "拷贝赋值函数被执行...\n";
        this->no = stu.no;
        this->age = stu.age;
    }
};


int main() {

    Student s1(10001, 15);
    Student s2(s1);  // 此处执行的是拷贝构造函数

    s2 = s1;  // 此处执行的是拷贝赋值函数

    return 0;
}

5、调用运算符重载
一般来说,可以使用对象来访问类中的成员函数,而对象本身是不能像函数一样被调用的,除非在类中重载了调用运算符。 如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象。在外面使用 对象(),实际上背后访问的是类中重载的调用运算符函数。

如果某个类重载了调用运算符,那么该类的对象即可称之为:函数对象 ,因为可以调用这种对象,所以才说这些对象行为 像函数一样。

#include<iostream>

using namespace std;

class Calc {
public:
    int operator()(int val) {
        return val < 0 ? -val : val;
    }
};

int main() {
    Calc c;
    int value = c(-10);

    cout << value << "\n";

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

挥剑决浮云 -

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

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

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

打赏作者

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

抵扣说明:

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

余额充值