当前位置: 首页 > article >正文

C++基础知识学习记录—运算符重载

1、概念

1、C++允许把运算符看做为一个函数,因此绝大多数运算符也支持函数重载。

2、C++中预定义的运算符只能对基本数据类型进行操作,但是对于很多用户自定义的类型,也需要类似的运算操作,此时就可以对这些运算符进行重载,赋予新的功能,根据新的数据类型执行特定的操作

3、运算符重载的本质是函数重载,它也是C++多态的一种体现

4、运算符重载增强了C++的可扩充性,使得C++代码更加直观、易读

C++提供的运算符重载机制,重载运算符是具有特殊名字的函数:它们的名字由关键字operator和其后要重载的运算符共同组成。和其他函数一样,重载运算符的函数也包括返回类型、参数列表及函数体。

可以被重载的运算符:

算术运算符:+、-、*、/、%、++、--

位操作运算符:&、|、~、^(位异或)、<<(左移)、>>(右移)

逻辑运算符:!、&&、||

比较运算符:<、>、>=、<=、==、!=

赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=

其他运算符:[]、()、->、,、new、delete、new[]、delete[]

不能被重载的运算符:

成员运算符“.”、指针运算符“*”、三目运算符“? :”、sizeof、作用域“::”

运算符重载既可以通过友元函数实现,又可以通过成员函数函数

2、友元函数运算符重载 

#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
    int num;
public:
    Test(int num)
        :num(num){   }

    //num的读接口
    int get_num() const
    {
        return this->num;
    }

    //+运算符重载的友元说明
    friend Test operator +(const Test& t1,const Test& t2);

    //前置++运算符重载的友元说明
    friend Test operator ++(Test& t);

    //后置++ 运算符重载友元说明   int是一个占位符,用来和前置++加以区分
    friend Test operator ++(Test& t,int);

};
int main()
{
    Test t1(11);
    Test t2(22);
    Test t3=t1+t2;
    cout << t3.get_num() << endl;//33

    Test t4(44);
    Test t5=++t4;
    cout << t5.get_num() << endl;//45
    cout << t4.get_num() << endl;//45

    Test t6(66);
    Test t7=t6++;
    cout << t7.get_num() << endl;//66
    cout << t6.get_num() << endl;//67

    return 0;
}

Test operator +(const Test& t1,const Test& t2)
{
    return t1.num+t2.num;
}
Test operator ++(Test& t)
{
    return ++t.num;
}
Test operator ++(Test& t,int)
{
    return t.num++;
}

3、成员函数运算符重载

成员函数,默认都有一个隐含的this指针,可以比友元函数重载少一个参数,隐含的this指针作为成员函数的第一个参数存在。

#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
    int num;
public:
    Test(int num)
        :num(num){   }

    //num的读接口
    int get_num() const
    {
        return this->num;
    }

    //+运算符重载的友元说明
    Test operator +(const Test& t);

    //前置++运算符重载的友元说明
    Test operator ++();

    //后置++ 运算符重载友元说明   int是一个占位符,用来和前置++加以区分
    Test operator ++(int);

};

Test Test::operator +(const Test& t)
{
    return this->num+t.num;
}
Test Test::operator ++()
{
    return ++this->num;
}
Test Test::operator ++(int)
{
    return this->num++;
}
int main()
{
    Test t1(11);
    Test t2(22);
    Test t3=t1+t2;
    cout << t3.get_num() << endl;//33

    Test t4(44);
    ++t4;
    cout << t4.get_num() << endl;//45

    Test t5(55);
    t5++;
    cout << t5.get_num() << endl;//56

    return 0;
}

4、特殊情况

1、赋值运算符重载

赋值运算符重载 = ,只能使用成员函数运算符重载,当程序员在一个类中不手写赋值运算符重载时,编译器会自动添加,默认的赋值运算符重载函数,其内容类似于拷贝构造函数。

作用:用于把一个对象的值赋值给另一个对象

形式:T& operator =(const T& t) //T可以是任意类型

特点:是类内函数,只支持成员函数重载

不显示给出赋值运算符函数时,编译器会给出默认的赋值运算符函数,完成对象间的赋值。

但是当属性有指针类型的时候,这时需要显示写出赋值运算符函数,类似于浅拷贝出现的问题

注意,当成员变量出现指针时,需要程序员手动编写赋值运算符重载逻辑,防止浅拷贝出现。 

#include <iostream>
#include <string>
#include <string.h>
using namespace std;

class Test
{
private:
    int num;
    char *name;
public:
    //深拷贝构造函数
    Test(int num,char* name)
    {
        this->num=num;
        this->name=new char [20];
        strcpy(this->name,name);
    }

    //手动添加编译器自带赋值运算符重载 浅拷贝
    /*Test& operator =(const Test& t)
    {
        this->num=t.num;
        this->name=t.name;
        return *this;
    }*/

     //手写赋值运算符重载  实现深拷贝
    Test& operator =(const Test& t)
    {
        this->num=t.num;
        this->name=new char[20];
        cout << "********" << endl;
        strcpy(this->name,t.name);
        return *this;
    }
    //num 读接口
    int get_num() const
    {
        return this->num;
    }

    //name读接口
    char* get_name() const
    {
        return this->name;
    }

};


int main()
{
    char ch[20]="admin";
    Test t1(2,ch);
    Test t2(3,"nancy");

    t2=t1;
    cout << t2.get_num() << endl;
    cout << t2.get_name() << endl;
    cout << endl;

    strcpy(t1.get_name(),"tttttt");
    cout << t1.get_name() << endl;
    cout << t2.get_name() <<endl;
    cout << endl;

    strcpy(ch,"wwww");
    cout << t1.get_name() << endl;
    cout << t2.get_name() <<endl;


    return 0;
}

2、类型转换运算符重载

这种情况的写法比较特殊,且必须使用成员函数运算符实现重载。

作用:把自定义类型转成任意类型

特点:

1、只支持成员函数重载

2、不需要写返回值类型

#include <iostream>

using namespace std;

class Test{
private:
    int num;
public:
    Test(int num)
        :num(num){    }

    //num 读接口
    int get_num() const
    {
        return  num;
    }

    //(int)t  转成整形的运算符重载
    operator int()
    {
        return this->num;
    }
   
};

int main()
{

    Test t1(100);//创建对象
    Test t2 = 90;//隐式调用构造函数  也会创建对象
    cout << t2.get_num() << endl;

    int b(t1); //会出现类型转换  把对象类型t转换成整形
    int res=(int)t2;//强制类型转换
    //cout << t << endl
    cout << res << endl;
    cout << b << endl;
    return 0;
}

3、运算符重载的总结

● 运算符重载只能限制在C++已有的运算符范围内,即不能创建新的运算符。

● 运算符重载不能改变运算符的优先级和结合性。

● 运算符重载不能改变运算符的操作数和语法结构。

● 无法更改已有的基本数据类型运算规则,只能应用于包含用户自定义类型的运算。

● 运算符重载应该保持与原有运算符功能类似,避免没有目的地滥用运算符重载。

● 运算符重载函数不支持参数默认值的设定。

一般情况下,单目运算符建议使用成员函数重载,双目运算符使用友元函数重载


http://www.kler.cn/a/552235.html

相关文章:

  • 【Golang 面试题】每日 3 题(五十八)
  • ubuntu平台下vim自动插件管理
  • [AI相关]Unity的C#代码如何简写
  • 构建高效智能对话前端:基于Ant Design X 的deepseek对话应用
  • Kafka的生产者和消费者模型
  • Go 语言函数返回对象 vs 传递指针赋值:性能对比与最佳实践
  • C#上位机--结构
  • Redis(高阶篇)03章——缓存双写一致性之更新策略探讨
  • 在华为云部署应用,通过阿里云代理调用第三方接口的利弊与解决方案
  • 机器学习(李宏毅)——RNN
  • 搭建一个 Spring Boot 项目,解决jdk与springboot版本不匹配
  • vue3中reactive的对象清空,所引发的问题:清空不了和清空之后再去赋值就赋值不了为什么
  • 年前集训总结python
  • 玩客云 IP查找
  • Gateway中的Filter机制
  • 解锁养生秘籍,拥抱健康生活
  • 【Scrapy】Scrapy教程6——提取数据
  • 【强化学习入门笔记】3.3 Actor-Critic方法: QAC,A2C
  • 使用IDEA创建Maven项目、Maven坐标,以及导入Maven项目
  • (新版本onenet)stm32+esp8266/01s mqtt连接onenet上报温湿度和远程控制(含小程序)