C++运算符重载——重载二元运算符
1、重载二元操作符的方法
二元运算符又称为双目运算符,即需要2个操作数的运算符,例如 + - * / 等。
运算符重载可以分为3种方式:类的非静态成员函数、类的友元函数、普通函数。
例如有 2 个操作数 a 和 b,二元运算符 ? (表示一个二元运算符),a ? b 的操作会被解释为下面2种形式之一
//a ? b
a.operator?(b); //类的非静态成员函数
operator?(a, b); //友元函数 和 普通函数
第一种形式是运算符被重载为类的非静态成员函数,
这种方式要求运算符左边的的操作数(即第一个操作数a)必须是一个对象,operator?是这个对象的非静态成员函数
并且只能有一个参数。
第二种形式是运算符被重载为类的友元函数 或 普通函数,
这种方式需要2个参数,
重载为 类的友元函数 和 普通函数的区别是 类的友元函数可以直接访问类的私有成员,而普通函数不可以。
2、应用举例(对象 ? 对象)
下例中有3个complex类 ComplexA、ComplexB 和 ComplexC,3个类都重载了加减乘除 运算符。
其中ComplexA使用类的非静态成员函数方式重载,ComplexB使用类的友元函数方式重载,ComplexC使用普通函数方式重载。
需要注意的是复数的加减乘除运算的算法是有问题的,只是一个说明重载方法的例子,
另外重载函数的参数最好使用const关键字限定,至于返回值是否用const限定,需要取决于你的设计,比如允许C3 = ++(C1+C2)这种情况,就不能用cosnt限定。
至于不同类型的对象间的操作,通常是没有意义的。
#include <iostream>
using namespace std; class ComplexA
{
public:
//默认构造函数(Default constructor)
ComplexA(){cout<<"Default Constructor"<<endl;}
//带参数的构造函数(The constructor with parameters)
ComplexA(double re, double im):real(re),image(im){cout<<"Parameter Constructor"<<endl;}
//拷贝构造函数(Copy constructor)
ComplexA(const ComplexA& ref){real = ref.real; image = ref.image; cout<<"Copy Constructor"<<endl;}
//析构函数(destructor)
~ComplexA(){cout<<"Destructor"<<endl;} //Operator Overload : +
ComplexA operator+(ComplexA& ref)
{
return ComplexA(real + ref.real, image + ref.image);
} //Operator Overload : -
ComplexA operator-(ComplexA& ref)
{
return ComplexA(real - ref.real, image - ref.image);
} //Operator Overload : *
ComplexA operator*(ComplexA& ref)
{
return ComplexA(real * ref.real, image * ref.image);
} //Operator Overload : /
ComplexA operator/(ComplexA& ref)
{
return ComplexA(real / ref.real, image / ref.image);
} //display
void display(void){cout<<real<<"+"<<image<<"i"<<endl;}
private:
double real; //复数的实部
double image; //复数的虚部
}; class ComplexB
{
public:
//默认构造函数(Default constructor)
ComplexB(){cout<<"Default Constructor"<<endl;}
//带参数的构造函数(The constructor with parameters)
ComplexB(double re, double im):real(re),image(im){cout<<"Parameter Constructor"<<endl;}
//拷贝构造函数(Copy constructor)
ComplexB(const ComplexB& ref){real = ref.real; image = ref.image; cout<<"Copy Constructor"<<endl;}
//析构函数(destructor)
~ComplexB(){cout<<"Destructor"<<endl;} //Operator Overload : +
friend ComplexB operator+(ComplexB& ref1, ComplexB& ref2)
{
return ComplexB(ref1.real + ref2.real, ref1.image + ref2.image);
} //Operator Overload : -
friend ComplexB operator-(ComplexB& ref1, ComplexB& ref2)
{
return ComplexB(ref1.real - ref2.real, ref1.image - ref2.image);
} //Operator Overload : *
friend ComplexB operator*(ComplexB& ref1, ComplexB& ref2)
{
return ComplexB(ref1.real * ref2.real, ref1.image * ref2.image);
} //Operator Overload : /
friend ComplexB operator/(ComplexB& ref1, ComplexB& ref2)
{
return ComplexB(ref1.real / ref2.real, ref1.image / ref2.image);
} //display
void display(void){cout<<real<<"+"<<image<<"i"<<endl;}
private:
double real; //复数的实部
double image; //复数的虚部
}; class ComplexC
{
public:
//默认构造函数(Default constructor)
ComplexC(){cout<<"Default Constructor"<<endl;}
//带参数的构造函数(The constructor with parameters)
ComplexC(double re, double im):real(re),image(im){cout<<"Parameter Constructor"<<endl;}
//拷贝构造函数(Copy constructor)
ComplexC(const ComplexC& ref){real = ref.real; image = ref.image; cout<<"Copy Constructor"<<endl;}
//析构函数(destructor)
~ComplexC(){cout<<"Destructor"<<endl;} //Get Data
double GetReal(void){return real;}
double GetImage(void){return image;} //display
void display(void){cout<<real<<"+"<<image<<"i"<<endl;}
private:
double real; //复数的实部
double image; //复数的虚部
}; //Operator Overload : +
ComplexC operator+(ComplexC& ref1, ComplexC& ref2)
{
return ComplexC(ref1.GetReal() + ref2.GetReal(), ref1.GetImage() + ref2.GetImage());
} //Operator Overload : -
ComplexC operator-(ComplexC& ref1, ComplexC& ref2)
{
return ComplexC(ref1.GetReal() - ref2.GetReal(), ref1.GetImage() - ref2.GetImage());
} //Operator Overload : *
ComplexC operator*(ComplexC& ref1, ComplexC& ref2)
{
return ComplexC(ref1.GetReal() * ref2.GetReal(), ref1.GetImage() * ref2.GetImage());
} //Operator Overload : /
ComplexC operator/(ComplexC& ref1, ComplexC& ref2)
{
return ComplexC(ref1.GetReal() / ref2.GetReal(), ref1.GetImage() / ref2.GetImage());
} int main(void)
{
ComplexA C1(,), C2(, ), C3;
C3 = C1 + C2; C3.display();
C3 = C1 - C2; C3.display();
C3 = C1 * C2; C3.display();
C3 = C1 / C2; C3.display();
cout <<"--------------------------------------"<<endl;
ComplexB C4(,), C5(, ), C6;
C6 = C4 + C5; C6.display();
C6 = C4 - C5; C6.display();
C6 = C4 * C5; C6.display();
C6 = C4 / C5; C6.display();
cout <<"--------------------------------------"<<endl;
ComplexC C7(,), C8(, ), C9;
C9 = C7 + C8; C9.display();
C9 = C7 - C8; C9.display();
C9 = C7 * C8; C9.display();
C9 = C7 / C8; C9.display();
return ;
}
3、应用举例(对象 ? 基本数据类型 or 基本数据类型 ? 对象)
上面的例子中是对象 和 对象之间的运算符重载,如果需要一个是对象 + char/int/float/double,或者反过来 char/int/float/double + 对象,这时上面的程序的重载方式就不适用了。
需要定义新的重载,如下列程序所示。
#include <iostream>
using namespace std; class ComplexD
{
public:
ComplexD(double re = , double im = ):real(re),image(im){} ComplexD operator+(ComplexD& ref){return ComplexD(real+ref.real, image+ref.image);};
ComplexD operator+(int a){cout<<"IN\t int \t\t";return ComplexD(real+a, image);};
ComplexD operator+(double d){cout<<"IN\t double \t";return ComplexD(real+d, image);};
ComplexD operator+(float f){cout<<"IN\t float \t\t";return ComplexD(real+f, image);}; void display(void){cout<<real<<"+"<<image<<"i"<<endl;}
double GetReal(void){return real;}
double GetImage(void){return image;}
private:
double real;
double image;
}; ComplexD operator+(int a, ComplexD& ref){cout<<"OUT\t int \t\t";return ComplexD(ref.GetReal()+a, ref.GetImage());};
ComplexD operator+(double d, ComplexD& ref){cout<<"OUT\t double \t";return ComplexD(ref.GetReal()+d, ref.GetImage());};
ComplexD operator+(float f, ComplexD& ref){cout<<"OUT\t float \t\t";return ComplexD(ref.GetReal()+f, ref.GetImage());}; int main(void)
{
ComplexD D1(,), D2;
D2 = D1 + ; D2.display();
D2 = D1 + 2.1f; D2.display();
D2 = D1 + 2.1; D2.display(); D2 = +D1; D2.display();
D2 = 2.1f + D1; D2.display();
D2 = 2.1 +D1; D2.display(); return ;
}
C++运算符重载——重载二元运算符的更多相关文章
- C++ 重载运算符和重载函数
C++ 重载运算符和重载函数 C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是 ...
- JavaScript一元运算符、二元运算符和三元运算符
在JavaScript中,运算符可以根据其实际操作数的个数进行分类. JavaScript中的大多数运算符是一个二元运算符(binary operator),将两个表达式合并成为一个稍复杂的表达式.譬 ...
- C++ 运算符重载一(二元运算符重载)
//二元运算符重载 #include<iostream> using namespace std; class Point { public: Point(int x,int y){ th ...
- C++之运算符重载(二元)
一.加号+ 1.成员函数重载 2.友元函数重载 二.输出符号<< 三.索引符号 [ ] 四.补充说明 1.<二元运算符重载>课程评论: (一)为什么<<运算符的重载 ...
- [置顶] C++基础之六:运算符的重载
网上太多有关运算符的重载了,但是写的太过的详细,不适合新手入门,特别是那什么++和--的前增量后增量重载,一元二元运算符重载,特殊运算符,下标运算符,new和delete,甚至是指针运算符的重载,吓退 ...
- C++解析七-重载运算符和重载函数
重载运算符和重载函数C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载.重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列 ...
- C++ 自增、自减运算符的重载和性能分析
01 ++.--运算符重载函数的格式 自增运算符和自减运算符是有前置和后置之分的,如: a++ // 后置自增运算符 ++a // 前置自增运算符 b-- // 后置自减运算符 --b // 前置自减 ...
- C++基础之自增和自减运算符的重载
1. 格式 1.1 分为前置和后置格式: int x = 0; int y = 0; // 后置自增运算符 x++; // 前置自增运算符 ++x; // 后置自减运算符 y--; // 前置自减运算 ...
- C++ Primer : : 第十四章 : 重载运算符与类型转换之类型转换运算符和重载匹配
类型转换运算符 class SmallInt { public: SmallInt(int i = 0) : val(i) { if (i < 0 || i > 255) throw st ...
随机推荐
- 51.ISE中的DCM全局时钟转为普通IO
在用DCM这个IP核时,它的输入时钟为全局时钟引脚输入,输出有两种情况,第一,可以直接接在全局时钟引脚:第二,可以通过ODDR2原语接在普通IO引脚:说下第二种是怎么用的: DCM DCM_INST ...
- 学习jax-ws(一)
1.生成文件时提示class not find ,需要加个cp .,这样就行了 E:\mylearn\learn_webservice\learnJax-ws\bin>wsgen -cp . w ...
- 团队小组开发nabc分析
我们团队开发的项目为:牛逼的手电筒 NABC模型: 1.N:现在每个人几乎走哪,干什么都会拿着手机,而现在年轻人晚上在外面的也不少,所以手机里安装一个手电筒的APP还是很有必要的. 2.A:这学期正在 ...
- 详谈socket请求Web服务器过程
最开始我们需要明白一件事情,因为这是这篇文章的前提: HTTP协议只是一个应用层协议,它底层是通过TCP进行传输数据的.因此,浏览器访问Web服务器的过程必须先有“连接建立”的发生. 而有人或许会问: ...
- jsp或Action获取请求参数中文乱码
普通情况下,中文字符会被自动转换成iso-8859-1的编码格式通过网络传输,而这种格式是没办法直接表示出我们认识的中文字符的,所以还要手动将他转换回之前的字符集. 一般在servlet或者actio ...
- SQL Server性能优化(3)使用SQL Server Profiler查询性能瓶颈
关于SQL Server Profiler的使用,网上已经有很多教程,比如这一篇文章:SQL Server Profiler:使用方法和指标说明.微软官方文档:https://msdn.microso ...
- ASP.NET MVC学习之视图篇(1)
一.前言 不知道还有多少读者从第一篇开始一直学习到如今,笔者也会一直坚持将ASP.NET MVC的学习完美的结束掉,然后开始写如何配合其他框架使用ASP.NET MVC的随笔.当然笔者后面的随笔如果没 ...
- 关灯问题 dp
题意是一排路灯,每个路灯有耗电量,照明度,需要给这n个路灯按顺序分组,每组内的最大耗电量是电灯数乘t,可以选择关闭一些电灯,求最大的照明度: 这题思路很明显,预处理出一个g[i][j]表示i到j分为一 ...
- depthstencil buffer 不支持 msaa
phyreengine dx11 MRT不支持 depth rendertarget 的msaa 他里面竟然只写着,// not supported yet !!!! 导致hdao 时开msaa的话, ...
- 常用的CSSreset整理
说道CSSreset,大家又爱又恨,cssreset好处是,覆盖了浏览器的默认样式,使前端攻城狮能更加精确的添加样式,各个浏览器中的界面效果都相同.可是大量的.固定的CSSreset也给网页加载带来一 ...