初识C++之运算符重载
来源:互联网 发布:创世传说 知乎 编辑:程序博客网 时间:2024/06/04 20:04
C++里面有一个叫作运算符重载的特性,它其实是基于函数实现的,下面就来介绍一下运算符重载。
1、What
C++中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型执行特定的操作。运算符重载的实质是函数重载,它提供了C++的可扩展性,也是C++最吸引人的特性之一。
运算符重载函数的定义与其他函数的定义类似,惟一的区别是运算符重载函数的函数名是由关键字operator和其后要重载的运算符符号构成的。运算符函数定义的一般格式如下:
返回值 opreator 运算符(参数列表)
{
函数体
}
当然,并不是所有运算符都可以实现重载,下面列举了能实现重载和不能实现重载的运算符。
2、Notice
a. 不能通过连接其他符号来创建新的操作符:比如operator@;
b. 重载操作符必须有一个类类型或者枚举类型的操作数;
int operator +(const int _iNum1 , const int _iNum2 ) // 报错 { return ( _iNum1 + _iNum2); } typedef enum TEST {one ,two ,three }; int operator+(const int _iNum1 , const TEST _test ) //正确 { return _iNum1; }
c. 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义;
d. 不再具备短求值特性
重载操作符不能保证操作符的求值顺序,在重载&&和||中,对每个操作数都要进行求值,而且对操作数的求值顺序不能做规定,因此:重载&&、||和逗号操作符不是好的做法。
e. 作为类成员的重载函数,其形参看起来比操作数数目少1
成员函数的操作符有一个默认的形参this,限定为第一个形参。
CTest operator+(const CTest test1, const CTest test2)const // 报错 { return test1; } CTest operator+(const CTest test1)const { return test1; }
f. 一般将算术操作符定义为非成员函数,将赋值运算符定义成员函数
g. 操作符定义为非类的成员函数时,一般将其定义为类的友元
h. == 和 != 操作符一般要成对重载
i.下标操作符[]:一个非const成员并返回引用,一个是const成员并返回引用
j. 解引用操作符*和->操作符,不显示任何参数
k. 自增自减操作符
前置式++/–必须返回被增量或者减量的引用
后缀式操作符必须返回旧值,并且应该是值返回而不是引用返回
l. 输入操作符>>和输出操作符<<必须定义为类的友元函数
3、Realize
通过一个复数类来深入认识运算符重载
#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>using namespace std;//实现复数类class Complex{public: Complex(const double real = 0.0, const double image = 0.0) :_real(real) , _image(image) { cout << "Create:" << this << endl; } Complex(const Complex& complex) :_real(complex._real) , _image(complex._image) { cout << "Copy Create:" << this << endl; } ~Complex() { cout << "Destroy:" << this << endl; } void Print() { cout << "real:" << _real << " image:" << _image << endl; } //实现各个运算符的重载 //= + - * / Complex& operator=(const Complex& complex) { if (this != &complex) { _real = complex._real; _image = complex._image; } return *this; } Complex operator+(const Complex& complex) { return Complex(_real + complex._real, _image + complex._image); } Complex operator-(const Complex& complex) { return Complex(_real - complex._real, _image - complex._image); } Complex operator*(const Complex& complex) { //复数乘法:(a+bi) * (c+di) = (ac-bd)+ (ad+bc)i return Complex((_real*complex._real - _image*complex._image), (_real*complex._image + _image*complex._real)); } Complex operator/(const Complex& complex) { //复数除法:(a+bi) / (c+di) = (ac+bd)/(c*c+d*d) + (bc-ad)i/(c*c+d*d) return Complex((_real*complex._real + _image*complex._image) / (complex._real*complex._real + complex._image*complex._image), \ (_image*complex._real - _real*complex._image) / (complex._real*complex._real + complex._image*complex._image)); } //+= -= *= /= Complex operator+=(const Complex& complex) { _real += complex._real; _image += complex._image; return *this; } Complex operator-=(const Complex& complex) { _real -= complex._real; _image -= complex._image; return *this; } Complex operator*=(const Complex& complex) { //因为下面的运算中用到的都是_real和_image的初始值,所以在这儿先把它们的初始值保存下来(temp2可以不用定义直接用_image) double temp1 = _real; double temp2 = _image; _real = temp1*complex._real - temp2*complex._image; _image = temp1*complex._image + temp2*complex._real; return *this; } Complex operator/=(const Complex& complex) { double temp1 = _real; double temp2 = _image; _real = (temp1*complex._real + temp2*complex._image) / (complex._real*complex._real + complex._image*complex._image); _image = (temp2*complex._real - temp1*complex._image) / (complex._real*complex._real + complex._image*complex._image); return *this; } //> >= < <= == != bool operator>(const Complex& complex) { return _real > complex._real; } bool operator>=(const Complex& complex) { return _real >= complex._real; } bool operator<(const Complex& complex) { return _real < complex._real; } bool operator<=(const Complex& complex) { return _real <= complex._real; } //上面四个函数只比较实部是因为:复数实部不为0,那么此时它是一个虚数,无法比较大小,这儿只是为了说明这几个运算符的 //重载是如何实现的,没有实际的逻辑意义 bool operator ==(const Complex& complex) { return (_real == complex._real) && (_image == complex._image); } bool operator !=(const Complex& complex) { return (_real != complex._real) || (_image != complex._image); } //前置++ -- Complex& operator++() { _real++; _image++; return *this; } Complex& operator--() { _real--; _image--; return *this; } //后置++ -- Complex operator++(int) { //因为后置的++和--,是先赋值,再++或--,所以这儿用一个临时变量来记住变量的值,然后把该变量自加1, //此时变量的值已经变了,但因为返回的是变量自加之前的值,所以整个表达式的值是该变量自加前的值 Complex temp(*this); _real++; _image++; return temp; } Complex operator--(int) { Complex temp(*this); _real--; _image--; return temp; } //逻辑运算 && || ! bool operator&&(const Complex& complex) { return ((_real != 0 || _image != 0) && (complex._real != 0 || complex._image != 0)); } bool operator||(const Complex& complex) { return ((_real != 0 || _image != 0) || (complex._real != 0 || complex._image != 0)); } bool operator!() { return !(_real != 0 || _image != 0); }private: double _real; double _image;};//Test Complex() / Complex(const Complex& complex) / ~Complex() / Print() void TestFun1(){ Complex c1; Complex c2(1.1, 2.2); Complex c3(c2); c1.Print(); c2.Print(); c3.Print();}//Test operator= / operator+ / operator- / operator* / operator/void TestFun2(){ Complex c1(1.1, 2.2); Complex c2(1.1, 2.2); Complex c3(0.0, 0.0); c3 = c2; Complex c4 = c1 + c2; Complex c5 = c1 - c2; Complex c6 = c1 * c2; Complex c7 = c1 / c2; c1.Print(); c2.Print(); c3.Print(); c4.Print(); c5.Print(); c6.Print(); c7.Print();}//Test operator+= / operator-= / operator*= / operator/=void TestFun3(){ Complex c1(1.1, 2.2); Complex c2(0.0, 0.0); Complex c3(0.0, 0.0); Complex c4(1.0, 1.0); Complex c5(1.1, 2.2); c2 += c1; c3 -= c1; c4 *= c1; c5 /= c1; c1.Print(); c2.Print(); c3.Print(); c4.Print(); c5.Print();}//Test operator> / operator>= / operator< / operator<= / operator== / operator!=void TestFun4(){ Complex c1(1.1, 2.2); Complex c2(0.0, 0.0); bool b1 = c1 > c2; bool b2 = c1 >= c2; bool b3 = c1 < c2; bool b4 = c1 <= c2; bool b5 = c1 == c2; bool b6 = c1 != c2; cout << b1 << ' ' << b2 << ' ' << b3 << ' ' << b4 << ' ' << b5 << ' ' << b6 << endl;}//Test operator++() / operator++(int) / operator--() / operator--(int)void TestFun5(){ Complex c1(1.1, 2.2); Complex c2(1.1, 2.2); Complex temp(0.0, 0.0); //因为要是直接用c1或c2输出,那么在输出时c1、c2的值已经是++或--运算的下一次使用了,因此用temp记住使用前的值 temp = ++c1; temp.Print(); temp = c1++; temp.Print(); temp = --c2; temp.Print(); temp = c2--; temp.Print();}//Test operator&& / operator|| / operator!void TestFun6(){ Complex c1(1.1, 2.2); Complex c2(0.0, 0.0); bool b1 = c1 && c2; bool b2 = c1 || c2; bool b3 = !c2; cout << b1 << ' ' << ' ' << b2 << ' ' << b3 << endl;}int main(){ //TestFun1(); //TestFun2(); TestFun3(); //TestFun4(); //TestFun5(); //TestFun6(); getchar(); return 0;}
- 初识C++之运算符重载
- 初识C#运算符重载
- 【C++】C++大数之运算符重载
- 【C++】之【运算符重载函数】
- C语言之重载运算符()/[]/++/->等运算符
- C++-运算符重载
- [C++]重载运算符
- C#:运算符重载
- c++-++运算符重载
- C++:重载运算符
- 运算符重载(C++)
- [c++]运算符重载
- 【C++】运算符重载
- C++--------------------------------------------运算符重载
- C#:运算符重载
- C++:运算符重载
- C++:运算符重载
- C#:运算符重载
- Android 一键加速原理
- tomcat优化方案(转)
- Java中的Synchronized,有时候没有那么简单
- 安装Yii碰到“the file or directory to be published does not exist bower/jquery/dist”
- MongoDB 分片的原理、搭建、应用
- 初识C++之运算符重载
- Android 升级SDK慢的问题
- Volley框架学习一
- winform中窗体最大化时 如何使窗体中内容也相应的全屏
- 数据库分库分表(sharding)系列(二) 全局主键生成策略
- 访问android官方网站
- Android ImageView深入理解
- java ArrayList 的实现
- JAVA内存管理常识