千家信息网

C++中如何实现运算符重载

发表于:2024-11-17 作者:千家信息网编辑
千家信息网最后更新 2024年11月17日,这篇文章主要为大家展示了"C++中如何实现运算符重载",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"C++中如何实现运算符重载"这篇文章吧。1、引例clas
千家信息网最后更新 2024年11月17日C++中如何实现运算符重载

这篇文章主要为大家展示了"C++中如何实现运算符重载",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"C++中如何实现运算符重载"这篇文章吧。

1、引例

class Complex{private:    double Real,Image;public:    Complex():Real(0),Image(0)  {}    Complex(double r, double i) : Real(r),Image(i) {}    ~Complex()  {}};int main(){    Complex c1(1.2,2.3);    Complex c2(45,56);    Complex c3;    c3 = c1.Add(c2);           }

类非常简单,下面我们要讨论如何写一个Add函数,使得两个对象的属性相加,返回一个新的对象。

第一种:

Complex::Complex Add(const Complex &c){    Complex co;    co.Real = this->Real + c.Real;    co.Image = this->Image + c.Image;    return co;}

问题1:如何写出最节省空间的Add函数?

第二种:

Complex::Complex Add(const Complex &c) const      {    return Complex(c.Real + this->Real, c.Image + this.Image);}

由于不需要改变调用对象的属性值,我们给this指针添加const 修饰。

分析过程如下:

问题2:为什么第一种方式不节省空间呢?

首先第一种的代码比较繁琐,并且在函数栈帧中又创建了一个对象(第3行)。并且函数类型是值传递类型(第6行),返回的是一个将亡值对象。那么整个Add函数空间会产生两个对象,造成空间的浪费。

第二中代码创建的是无名对象,减少了一个co对象的创建,并且将无名对象直接作为将亡值对象传递给main函数中的c3。

问题3:我们能否将Add函数改为引用类型,这样来减少将亡值对象的创建

Complex::Complex &Add(const Complex &c) const      {    return Complex(c.Real + this->Real, c.Image + this.Image);}

VS2019发现报错,不能返回引用对象:

我们进行分析:

问题4:我们能否将这个Add函数名改为 + 运算符?

//Complex::Complex Add(const Complex &c) constComplex::Complex +(const Complex &c) const {        Complex co;        co.Real = this->Real + c.Real;        co.Image = this->Image + c.Image;        return co;}int main(){    ...    //c3 = c1.Add(c2);      c3 = c1.+(c2);    //将原先Add的地方改变为加号。    ...}       

这样使用,编译器又会报错,操作符不可作为一个有效的函数名来被使用

问题5:如何使 +预算符 作为函数名使用?

这就引出了今天的关键,函数运算符重载

在C++中,为了使操作符作为一个有效的函数名,我们在操作符前面添加一个operator

Complex operator+(const Complex &c) const {     return Complex(c.Real + this->Real,c.Image + this->Image);}int main(){     Complex c1(1.2,2.3);     Complex c2(10,10);     Complex c3;     c3 = c1 + c2;         //上面一行实际上是     //c3 = c1.operator+ (c2);     //c3 = operator+(&c1,c2);  //编译器还会经过一次编译}

前面几篇博客已经分析了第15行的由来,是将c1的地址传递给this指针,将c2作为形参c的别名传递给函数。

2、类中自动建立的函数

在C++中,如果我们定义一个类,它会给我们自动创建六个缺省函数

构造函数析构函数拷贝构造函数赋值函数普通对象的&(取地址符)的重载常对象的&(取地址符)重载

代码示例如下:

class Object{public:    Object()    {}                                                      //构造函数    ~Object()   {}                                                   //析构函数    Object(const Object &obj)   {}                     //拷贝构造函数    Object &operator=() {const Object &obj} //赋值函数    {        return *this;    }        Object *operator&()                                            //普通对象的&(取地址符)的重载    {        return this;    }        const Object *operator&() const                      //常对象的&(取地址符)重载    {        return this;    }};

然后,在C11标准下,又增添了两个缺省函数,这里不做深究:

移动构造函数移动赋值函数

3、重载赋值运算符解析

回到最初的例子:

class Object{    int value;public:    Object ()   {        cout << "create:" << this << endl;    }                  //普通构造函数    Object (int x = 0):value(x) {cout << "create:" << this << endl;}  //缺省构造函数    ~Object()                       //析构函数    {        cout << "~Objcet() " << this << endl;    }    Object(Object &obj):value(obj.value)                 {        cout << "Copy create:" << this << endl;    }    int & Value()    {        return value;    }    const int &Value() const     {        return value;    }              Object &operator=(const Object& obj)        //此处加引用    {        this->value = obj.value;        return *this;       //this指针指向objb的地址。赋值函数结束后,objb不会被消亡,所以可以以引用返回    }            void operator=(const Object& obj)       //赋值语句不可给this指针加const    {        this->value = obj.value;    }    };int main(){    Object objx(0);    Object objy(0);    objy = fun(objx);    cout << objy.Value() << endl;    return 0;}

我们在34行添加一个等号运算符重载函数: void operator=(const Object& obj)

此处不可添加const修饰this指针,因为需要使用this指针作为左值被修改。

问题6:void operator=(const Object& obj) 只能用于 obja = objb,为什么不可以这样使用 obja = objb = objc;

我们逐一分析:

obja = objb = objc;//当调用等号运算符函数的时候。obja = objb.operator = (objc);obja = operator = (&objb,objc);//如果此处是调用的是 void operator=(const Object& obj) ;//等号从右向左指向,我们不能把一个void 类型赋给一个obja对象类型。

我们将赋值运算符进行再次重载,丢弃 void 版本:

Object &operator=(const Object& obj)        //此处加引用{        this->value = obj.value;        return *this;       //this指针指向objb的地址。赋值函数结束后,objb不会被消亡,所以可以以引用返回}

这样就可以使用了。

我们接着上次的深入分析:

obja.operator=(operator=(&objb,objc));operator=(&obja,operator=(&objb,objc));

问题7:如果遇到obja = obja这种情况,如何赋值呢?

回答:对this指针和形参引用进行判断。

Object &operator=(const Object &obj){    if(this != &obj)    {        this->value = obj.value    }}

问题8:为什么函数是在栈区构建的,以引用返回打印的不是一个随机值?

运行程序,VS2012中,打印的是一个随机值。

VS2019打印的是一个正常值。

c));

> 问题7:如果遇到obja = obja这种情况,如何赋值呢?>> 回答:对this指针和形参引用进行判断。```cppObject &operator=(const Object &obj){    if(this != &obj)    {        this->value = obj.value    }}

问题8:为什么函数是在栈区构建的,以引用返回打印的不是一个随机值?

运行程序,VS2012中,打印的是一个随机值。

VS2019打印的是一个正常值。

在WIN10系统中,VS2019与操作系统完全结合,安全性更高。当程序多次运行的时候,它的逻辑地址都不一样,这样做的好处是:当病毒入侵时,由于程序的逻辑地址是变化的,病毒不好寻找入侵的入口。

以上是"C++中如何实现运算符重载"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

函数 对象 问题 运算符 运算 地址 指针 C++ 类型 分析 程序 空间 普通 两个 代码 内容 指向 操作符 等号 篇文章 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 长沙游戏软件开发地址 我和网络安全心得体会 数据库结构分为户级 济南善翰互联网科技有限公司 oracle数据库建立案例 全球十三台互联网服务器 支持256g内存的服务器主板 小程序服务器费用 北农商软件开发中心总经理 数据库系统原理数据库和表的创建 勤哲excel服务器说明书 兰州2021网络安全技术大赛 软件开发企业销售软件增值税率 2021年网络安全知识竞答案 华诺星空嵌入式软件开发笔试 普陀区互联网络技术服务模式 速达4000无法打开帐套数据库 岗位定位软件开发 网络技术本科学校 网络技术术语百度免费 阿里服务器换系统 大兴安岭网络安全宣传视频 网络安全一年级宣传画 网络安全科技馆感悟 数据库查询每个院系的最高成绩 软件开发与制作的实训心得 国泰安数据库净资产增长率 数据库并发操作两种方法 avc服务器 行业技术信息数据库模版
0