一元运算符重载

-------------------siwuxie095

在 C++ 中,运算符重载既是重点,也是难点

那么,什么是运算符重载呢?

所谓 运算符重载,就是给原有运算符赋予新的功能

如:原来的加号 + 是用来做数字相加操作的,但我们往往

会用加号 + 去做两个字符串的拼接,其实这就是给加号 +

做了运算符的重载

看如下实例:

在 main() 函数中就使用了加号 + 去连接多个字符串,使之拼接成

一个字符串,而且打印时也可以将这个字符串直接打印出来

那么这个字符串就进行了多个运算符的重载,即 加号运算符 + 、

等号运算符 =、输出运算符 << 都进行了重载

再看另一个实例:

在 main() 函数中有两个坐标,它们其实也是可以进行相加的,

相加之后形成一个新的坐标

但是,坐标相加,对于加号 + 本身来说,并不具备这样的功能,

为了能够让它具备这样的功能,就可以通过运算符重载来实现

同时,如果想直接输出一个坐标,也可以通过重载输出运算符

<< 来做到

运算符重载的本质,其实就是函数重载,它并没有神秘的地方

定义运算符重载的关键字:operator,即 运算符

运算符重载有很多种,包括 一元运算符重载、二元运算符重载 …

一元运算符重载

所谓 一元运算符,即 这个符号只与一个操作数进行运算

(1)负号 - 的重载

负号 - 的重载方式有两种:

第一种是友元函数重载,即 在类中定义一个全局函数作为友元函数,

用这个友元函数来做运算符的重载,从而实现一个符号多了一项功能

第二种是成员函数重载,其实就是定义一个类的成员函数

1)先来看成员函数重载,如下:

定义一个坐标类:Coordinate

如果想对负号 - 做成员函数的重载,应该写成这样:Coordinate 接一个

引用,然后是关键字 operator,后面是负号 -,然后是一对括号

因为是一元运算符,而且是作为类的成员函数存在的,所以不需要在其中

传任何的参数

在实现时:

虽然没有传参数,但作为一个普通的成员函数来说,它还是有一个隐性的

this 指针的,而这个隐性的 this 指针其实就是它的一个操作数,那么就可

以将每一个数据成员取反,重新赋值给本身,使得它所有的数据成员都由正

变为负 或 都由负变为正,然后将 *this 作为返回值返回出去即可

在使用时:

在 main() 函数中先定义一个 Coordinate 的对象 coor1,只需要在

coor1 的前面取一个负号,就会使得 coor1 的所有值都会取反,就

相当于是用 coor1 去调用 operator-() 这个函数

即 -coor1; 和 coor1.operator-(); 是等价的

在计算机解释时,当遇到 -coor1 这样的表示符号,计算机就会把它

解释为一个函数的调用

2)再来看友元函数的重载,如下:

此时,使用友元声明,通过 friend 来声明一个全局函数 operator-(),

并传入参数 Coordinate 的一个引用,它的返回值也是 Coordinate 的

一个引用

在实现时:

通过引用变量分别对它的每一个数据成员取反,并赋值给本身,

最后将 *this 返回回去

在使用时:

当给对象 coor1 取反时,计算机就会把它解释为 operator-(coor1);

比对成员函数重载和友元函数重载:

对于成员函数重载,写的是 coor1.operator-();

对于友元函数重载,写的是 operator-(coor1);

(2)自增符号 ++ 的重载

自增符号 ++ 的重载方式有两种:一种是 前置++,一种是 后置++

1)先来看 前置++ 的重载,如下:

如果想要做 ++ 运算符的前置重载,并把它当做成员函数来操作的话,

可以这样写:Coordinate& operator++();,因为它是一个一元运算符,

所以这里也不传入任何参数

在实现时:

作为成员函数来进行定义,使它的每一个成员都做 ++ 操作,最后将

*this 作为返回值返回出去,即 外面接收到的值其实就是 ++ 之后的

值了

在使用时:

如果调用 ++coor1;,就相当于调用 coor1.operator++();, 相当于在

调一个普通的成员函数

如果传入的是 3 和 5,在 ++ 之后,就变成了 4 和 6

2)再来看 后置++ 的重载,如下:

计算机要对 后置++ 和 前置++ 进行区分,所以 后置++ 需要特别注意:

返回值不再是引用,而是 Coordinate 的一个对象,同时,参数一定要传入

一个 int,这里的 int 是一个标识,它标识当前的 ++ 符号做的是后置重载,

在使用时,这个 int 并不传入任何值,即便是传入任何值也没有意义,因为

根本就不去使用它,只是一个标识而已

在实现时:

首先要保证有一个旧的值,即 先要定义一个临时对象 old,然后将当前

的值 *this 先保存到临时对象 old 当中,最后通过 return 将 old 返回出

如果在当前行接收到 后置++ 的值,那么 后置++ 的值也是没有 ++

之前的值,但是在下一行代码中如果再去使用当前对象时,里面的值

就已经发生变化了

在使用时:

如果调用 coor1++;,就相当于调用 coor1.operator++(0);,即 系统

会默认为我们传入一个值,一般来说是 0,它没有什么意义,但能够表

达出这是一个在调用 后置++ 的运算

程序 1:

Coordinate.h:


#ifndef COORDINATE_H

#define COORDINATE_H

#include <iostream>

using namespace std;

class Coordinate

{

// 友元函数的负号运算符重载

//与注释掉的成员函数的负号运算符重载进行对比

friend Coordinate &operator-(Coordinate &c);

public:

Coordinate(int x, int y);

//成员函数的负号运算符重载

//Coordinate &operator-();

int getX();

int getY();

private:

int m_iX;

int m_iY;

};

#endif

Coordinate.cpp:


#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)

{

m_iX = x;

m_iY = y;

}

int Coordinate::getX()

{

return m_iX;

}

int Coordinate::getY()

{

return m_iY;

}

//Coordinate &Coordinate::operator-()

//{

// // this->m_iX=-this->m_iX; this->m_iX=-(this->m_iX); 均可注意隐形的this指针

// m_iX = -m_iX;

// m_iY = -m_iY;

// return *this;

//}

//友元全局函数

Coordinate &operator-(Coordinate &c)

{

c.m_iX = -c.m_iX;

c.m_iY = -c.m_iY;

return c;

}

main.cpp:


#include "stdlib.h"

#include "Coordinate.h"

int main(void)

{

Coordinate coor(3, 5);

cout << coor.getX() << "," << coor.getY() << endl;

//成员函数重载

//-coor;//coor.operator-(); //可以尝试 -(-coor); 负负得正

//友元函数重载

-coor;// operator-(coor);

cout << coor.getX() << "," << coor.getY() << endl;

system("pause");

return 0;

}

程序 2:

Coordinate.h:


#ifndef COORDINATE_H

#define COORDINATE_H

#include <iostream>

using namespace std;

class Coordinate

{

public:

Coordinate(int x, int y);

//前置++ 因为是一元运算符在做成员函数重载时就不需要传入参数

Coordinate &operator++();

//后置++ 有一个参数 int 其实是一个标志型参数

//告诉编译器当前所做的++运算符重载是后置++的运算符重载

//

//编译器看到int后就会把它当做后置++的运算符重载标志

//返回值亦不一样返回的是Coordinate的一个对象而不是一个引用

Coordinate operator++(int);

int getX();

int getY();

private:

int m_iX;

int m_iY;

};

//因为表达式前置++ 此时表达式的值就是++之后的值

//把表达式++之后的值当做整个表达式的值就是前置++的实现方式

//

//而表达式后置++ 当前的表达式是++之前的那个值而下一行代码

//再去访问这个对象时才是++之后的这个对象的值所以实现时也要进行特别区分

#endif

Coordinate.cpp:


#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)

{

m_iX = x;

m_iY = y;

}

int Coordinate::getX()

{

return m_iX;

}

int Coordinate::getY()

{

return m_iY;

}

//返回出去的值应该是作了++之后的值对每一个数据成员都要做一次++

Coordinate &Coordinate::operator++()

{

m_iX++;// ++m_iX; 均可并不影响函数最终的效果

m_iY++;//++m_iY;

return *this;

}

Coordinate Coordinate::operator++(int)//注意不要漏了int

{

//先做一个临时对象temp 或者old 采用直接赋值将 *this 放进去

//用到了拷贝构造函数(因为没有指针并且没有在构造函数中申请内存,

//所以这里是默认的拷贝构造函数)

Coordinate old(*this);

this->m_iX++;

this->m_iY++;

//return的是old 这样就能实现当前表达式所拿到的是this ++之前的值

//而在当前表达式之后再去运行的代码所拿到的对象则是this ++之后的值

//这样就实现了后置++的效果

return old;

}

main.cpp:


#include "stdlib.h"

#include "Coordinate.h"

int main(void)

{

Coordinate coor(3, 5);

cout << coor.getX() << "," << coor.getY() << endl;//3,5

++coor;

cout << coor.getX() << "," << coor.getY() << endl;//4,6

cout << (coor++).getX() << ",";//x=4

cout << (coor++).getY() << endl;//y=7

cout << coor.getX() << "," << coor.getY() << endl;//6,8

system("pause");

return 0;

}

【made by siwuxie095】

时间: 2024-10-07 20:12:45

一元运算符重载的相关文章

C++一元运算符重载

#include <iostream> using namespace std; class Integer {   long i;   Integer* This() { return this; } public:   Integer(long ll = 0) : i(ll) {}   // No side effects takes const& argument:   friend const Integer&     operator+(const Integer&a

《C++编程思想》 第十一章 运算符重载 (习题+解答)

一.相关代码 1. /*运算符重载语法*/ /*OPOVER.cpp*/ /*这两个重载的运算符被定义为内联成员函数.对于二元运算符,单个参数是出现在运算符 右侧的那个.当一元运算符被定义为成员函数时,没有参数.成员函数被运算符左侧的对象调 用. 对于非条件运算符(条件运算符通常返回一个布尔值),如果两个参数是相同的类型,希 望返回和运算相同类型的对象或引用.如果它们不是相同类型,它作什么样的解释就取决于程 序设计者.用这种方法可以组合复杂的表达式: K += I + J ; 运算符+号产生一个

新标准C++程序设计读书笔记_运算符重载

形式 返回值类型 operator 运算符(形参表) { …… } 运算符重载 (1)运算符重载的实质是函数重载(2)可以重载为普通函数,也可以重载为成员函数 1 class Complex 2 { 3 public: 4 double real,imag; 5 Complex( double r = 0.0, double i= 0.0 ):real(r),imag(i) { } 6 Complex operator-(const Complex & c); 7 }; 8 9 Complex

运算符重载 学习总结

一元运算符重载 参考https://www.imooc.com/video/9588 - 号 友元函数重载 略 成员函数重载 class A{ public: A& operator-(); private: int m_a; int m_b; } A& A::operator-();{ m_a = -m_a; m_b = -m_a; return *this; } ++号(前置与后置) 略 二元运算符重载 参考https://www.imooc.com/video/9591 +号 成员函

【Python】面向对象的运算符重载

面向对象的编程中可以对运算符进行重载,使运算符可以对该类的实例进行操作. 重载方法的一般格式如下: 1 def __运算符名__(self, other): 2 运算符语句 比较常用的运算符重载有三类:二元算术运算符重载.反向算术运算符重载.比较运算符重载.一元运算符重载 1 二元算术运算符的重载: 2 方法名                  运算符和表达式      说明 3 __add__(self,rhs)        self + rhs      加法 4 __sub__(self

C++ STL vector容器学习

STL(Standard Template Library)标准模板库是C++最重要的组成部分,它提供了一组表示容器.迭代器.函数对象和算法的模板.其中容器是存储类型相同的数据的结构(如vector,list, deque, set, map等),算法完成特定任务,迭代器用来遍历容器对象,扮演容器和算法之间的胶合剂. 模板类vector 在计算中,矢量(vector)对应数组,它的数据安排以及操作方式,与array非常类似.在C++中,使用vector模板类时,需要头文件包含#include<v

九、C# 合式类型

本章要描述如何最终完善类型声明. 1.重写Ojbect中的成员 重写ToString() 默认情况下,在任何对象上调用 ToString()会返回类的完全限定名称,所以有时候需要重载这个函数,来实现更有意义的功能. 重写GetHashCode() 当想要重写Equals()的时候,就应该重写GetHashCode(). 在将类作为散列表集合的键使用时,最好 也将GetHashCode()重写. 散列码的作用是生成与对象的值对应的一个数字,从而高效地平衡一个散列表. 重写GetHashCode()

2015-02-25

今天最主要的就是搞定c++的运算符重载,还有两个小细节没有弄,就明天弄吧. 今天还看了malloc,free和new,delete的区别,nullptr和NULL的区别,const对象问题. 我们一个一个的说,首先说malloc,free,new,delete的区别吧.malloc可以分配内存,但是不调用构造函数,new会分配内存并且自动调用构造函数,free会释放内存但是不会调用析构函数,delete会释放内存也会调用析构函数.综上所述,所以我们c++的对象还是适合new出来的.new Gir

C# 语言规范_版本5.0 (第0章 目录)

C# 语言规范 版本5.0 注意 © 1999-2012 Microsoft Corporation.保留所有权利. Microsoft.Windows.Visual Basic.Visual C# 和 Visual C++ 是 Microsoft Corporation 在美国和/或其他国家/地区的注册商标或商标. 本文提及的其他产品和公司名称可能是其各自所有者的商标. 目录 1. 介绍......................................................