c++之运算符重载

一、 运算符重载

1. 什么是运算符重载

重载这个概念在早前的函数重载,大家已经见识过了。函数可以重载, 运算符也是可以重载。 运算符重载就是对已有的运算符重新进行定义,赋予其另一种功能,以达到适应不同的数据类型。运算符重载不能改变它本来的寓意(也就是 加法不能变更为 减法)

运算符重载只是一种 “语法上的方便” , 它只是一种函数调用的方式。

int a = 3 ;
int b = 4 ; 

int c = a + b ; //编译器通过

Student s1 ; 
Student s2 ; 

Student s3 = s1 + s2 ; // 编译器不通过

2. 定义运算符重载

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。假如我们需要把两个学生的年纪 和 体重 各自相加,然后得出第三个学生的数值。那么使用运算符重载可以如此编写:

  • 以前写法
class Student{
  
public:
    int age ;
    int weight;
    
public :     
    Student(age_val , weight_val):age{age_val},weight{weight_val}{
        
    }
    
};




Student s1(18 , 120);
Student s2(20 , 90);

int age = s1.age + s2.age ;
int weight = s1.weight  + s2.weight ;
Student s3 (age , weight);

  • 运算符重载

运算符可以写成全局函数也可以写成成员函数。

  1. 全局函数
Student operator+ (Student &s1 , Student &s2){
    Student temp(s1.age + s2.age , s1.weight + s2.weight);
    return temp;
}
  1. 成员函数
Student operator+ ( Student &s2){
    Student temp(this.age + s2.age , this.weight + s2.weight);
    return temp;
}

3. 运算符重载练习

1. 输出运算符重载

其实这里说就是我们平常见过的 <<<< 实际上是位移运算符,但是在c++里面,可以使用它来配合cout进行做控制台打印输出。 cout 其实是ostream 的一个实例,而ostrem 是 类basic_ostream的一个别名,所以之所以能使用cout << 来输出内容,全是因为 basic_ostream里面对 << 运算符进行了重载.

#include <iostream>  //由于这里引入了iostream 所以下面可以直接对 << 进行重载

class Student{
public:
   string name {"zhangsan"};

public:
   Student(string name){
       this->name = name;
   }
};

//对 << 运算符进行重载。
ostream& operator<< (ostream& o, Student &s1){
    o << s1.name ;
    return o;
}


int main() {
    Student s1("张三");
    cout << s1  <<"i" ;
    return 0;
}

2. 输入运算符重载
#include <iostream>  //由于这里引入了iostream 所以下面可以直接对 << 进行重载

//对 << 运算符进行重载。
ostream& operator<< (ostream& o, Student &s1){
    o << s1.name ;
    return o;
}

//对 >> 运算符进行重载
istream& operator>> (istream& in, Student &s1){
    in >> s1.name;
    return in;
}


int main() {
    Student s1("张三");
    cout << s1  <<"i" ;
    return 0;
}

4.赋值运算符重载

  • 默认的赋值运算符

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

stu s1;
stu s2;

s2= s1; //拷贝赋值

s2 = move(s1); // 一旦有这行代码,表示s1不能用了。
class Student{
 	int no;
    int age ;
    
public :
    Student(no , age){
        this->no = no ;
        this->age = age ;
    }
}

Student s1(10001 , 15);
Student s2 ;
s2 = s1; //此处使用了默认的赋值运算符。


Student s2 = s1;
1. 拷贝赋值运算

其实这里说的就是 = 赋值运算符

 //拷贝赋值
Stu& operator=(const Stu &h){
    cout <<"执行拷贝赋值函数" << endl;
    d = new int();
    *d = *h.d;
}
  • main
int main(){
    Stu stu1("张三",18);
	Stu stu2 ;

	stu2 = stu1; //拷贝赋值
}
2. 移动赋值运算

移动赋值运算,接收的是一个右值,并且移动之后,原有对象将不再拥有对数据的控制权。

 //移动赋值
Stu& operator=(const Stu &&h){
    cout <<"执行移动赋值函数" << endl;
    d = h.d;
    h.d = nullptr;
    
    return *this;
}

  • main
int main(){
     Stu stu1("张三",18);
	Stu stu2 ;

	stu2 = move(stu1); //移动后,stu1 将不再拥有对数据的控制权
}

5. 调用运算符重载

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

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

class Calc{ 
public:
    int operator()(int val){
        return val <0 ? -val :val;
    }
};
int main(){
    Calc c ;
    int value = c(-10);
    return 0;
}

  • 标准库中定义的函数对象

在标准库中定义了一组算术运算符 、关系运算符、逻辑运算符的类,每个类都有自己重载的调用运算符。要想使用这些类,需要导入 #include<functional> , 后面要说的 lamdda表达式 正是一个函数对象

 plus<int > p; //加法操作
int a = p(3 , 5);

negate<int> n; //可以区绝对值
cout <<n(-10) << endl;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值