首先回忆下以前学的函数重载

函数重载

  • 函数重载的本质为相互独立的不同函数
  • 通过函数名函数参数来确定函数调用
  • 无法直接通过函数名得到重载函数的入口地址
  • 函数重载必然发生在同一个作用域

类中的函数重载

  • 静态成员函数能与普通成员函数建立重载关系
  • 全局函数和成员函数不能构成重载关系

操作符重载(operator)

什么是操作符重载?

大家都知道,在C里,有'+,-,*,/'这些操作符,且它们的功能就是实现普通变量运算。

由于C++是面向对象的,遇到的变量大多都是对象,所以优化了C里的操作符,使它们拥有了重载能力.能通过一定方式,使对象能进行'+,-,*,/'等运算.

操作符的重载是以函数的方式进行.

操作符重载定义

操作符重载,通过operator关键字在函数前定义:

[返回类型]  operator  [需要重载的操作符](函数参数)

{

       //......

}

操作符重载有几种方式 : 全局操作符重载函数、全局操作符重载函数

编译器首先会判断运算的若是对象,就会先从类里寻找成员操作符重载函数,若没找到,就会再去全局里寻找全局操作符重载函数.

注意事项:

  • 操作符重载不能改变原操作符的优先级
  • 操作符重载不能改变操作数的个数
  • 操作符重载的参数一般设为const class_name &类型(若只设为const class_name,会产生临时对象)
  • 在C++中,有些操作符必须需要有对象支持,所以只能为成员函数.这种被称为一元操作符

比如赋值(=)、下标([])、下标([])、调用(())和成员访问箭头(->):

Test t3=t2;   //相当于调用了: Test  t3.operator =(t2);  里面会通过this指针来代替左侧数t3
  • 有些操作符既可以当做成员操作符重载函数,也可以当做全局操作符重载函数,由于函数参数可以多个,便称为二元操作符

比如加法(+),与(&&),或(||),逗号(,)等:

以加法(+)为例,当设为全局操作符重载函数时,执行

Test t3=t1+t2;  //相当于调用了:  Test t3 = operator +(t1,t2); 

以加法(+)为例,当设为成员操作符重载函数时,执行

Test t3=t1+t2;  //相当于调用了:  Test t3 =t1.operator +(t2);  //里面会通过this指针来代替左侧数t1

多个重载的操作符重载函数

由于操作符重载函数带参数,所以可以存在多个相同的操作符重载函数

例如:

class Test
{ double x; double y; public: Test operator +(const Test& t); //实现Test t3=t1+t2 Test operator +(int i); //实现Test t3=t1+1 Test operator +(double d); //实现Test t3=t1+1.25 //... ... };

  

初步试验

1.接下来,来个全局操作符重载函数例子:

#include "stdio.h"

class Test{

       int x;
int y; public:
Test(int x=0,int y=0)
{
this->x=x;
this->y=y;
}
int getx()
{
return x;
}
int gety()
{
return y;
} friend Test operator + (const Test& t1,const Test& t2);
//声明友元函数,可以使用私有成员变量 }; Test operator + (const Test& t1,const Test& t2) //重载
{
Test ret;
ret.x=t1.x+t2.x;
ret.y=t1.y+t2.y;
return ret;
} int main()
{
Test t1(1,3);
Test t2(2,4);
Test t3= t1 + t2; // 其实就是调用: Test t3 = operator +(t1,t2); printf("t3.x:%d t3.y:%d\n",t3.getx(),t3.gety()); Test t4 =operator +(t1,t3); // t4 =t1 +t3 printf("t4.x:%d t4.y:%d\n",t4.getx(),t4.gety()); return 0;
}

打印结果:

t3.x:3  t3.y:7
t4.x:4 t4.y:10

  

2.换成成员操作符重载函数例子:

#include "stdio.h"

class Test{

       int x;
int y; public:
Test(int x=0,int y=0)
{
this->x =x;
this->y =y;
} int getx()
{
return x;
} int gety()
{
return y;
} Test operator + (const Test& t2)
{
Test ret; ret.x = this->x + t2.x;
ret.y = this->y + t2.y;
return ret;
}
}; int main()
{
Test t1(1,3);
Test t2(2,4);
Test t3= t1 + t2; // 其实就是调用: Test t3 =t1.operator +(t2); printf("t3.x:%d t3.y:%d\n",t3.getx(),t3.gety()); Test t4 =t1.operator +(t3); // t4 =t1 +t3 printf("t4.x:%d t4.y:%d\n",t4.getx(),t4.gety()); return 0;
}

打印结果:

t3.x:3  t3.y:7
t4.x:4 t4.y:10

  

加深理解

由于C++里,没有复数的慨念,而在刚刚又学习了操作符重载,所以接下来便通过操作符重载来实现复数类

复数类应该具有

两个成员

实部a 、虚部b

运算操作符

+ - :  结果 = 两个实部进行加减,两个虚部进行加减

*   :  结果 = (a1+b1)(a2+b2)= (a1*a2 - b1*b2 )+( a2*b1 + a1*b2);

/   :  结果 =(a1+b1)/(a2+b2)= (a1*a2+b1*b2)/(a2* a2+b2* b2) +(b1*a2-a1*b2)/(a2* a2+b2* b2)

比较操作符:== ,!=

赋值操作符: =

求模成员函数 : 等于a^2+b^2的算术平方根

所以复数类的操作符重载共有以下几个:

1.写头文件Complex.h:

#ifndef __COMPLEX_H
#define __COMPLEX_H class Complex{ private:
double a;
double b; public:
Complex(int a=0,int b=0);
Complex operator + (const Complex& t);
Complex operator - (const Complex& t);
Complex operator * (const Complex& t);
Complex operator / (const Complex& t);
bool operator == (const Complex& t);
bool operator != (const Complex& t);
Complex& operator = (const Complex& t); double getModulus(); double getA();
double getB();
}; #endif

2.写源文件Complex.cpp

#include "Complex.h"
#include "math.h" Complex::Complex(int a,int b)
{
this->a = a;
this->b = b;
} Complex Complex::operator + (const Complex& t)
{
Complex ret; ret.a = a + t.a;
ret.b = b + t.b;
return ret;
} Complex Complex::operator - (const Complex& t)
{
Complex ret; ret.a = a - t.a;
ret.b = b - t.b;
return ret;
} Complex Complex::operator * (const Complex& t)
{
Complex ret;
ret.a = (a* t.a - b* t.b );
ret.b = (t.a *b + a* t.b );
return ret;
} Complex Complex::operator / (const Complex& t)
{
Complex ret;
ret.a = (a* t.a + b* t.b)/(t.a * t.a + t.b * t.b);
ret.b = (b* t.a - a* t.b)/(t.a * t.a + t.b * t.b);
return ret;
} bool Complex::operator == (const Complex& t)
{
if((a== t.a)&&(b== t.b))
return true; else
return false;
} bool Complex::operator != (const Complex& t)
{
if((a!= t.a)||(b!= t.b))
return true; else
return false;
} Complex& Complex::operator = (const Complex& t)
{
if(this != &t)
{
a = t.a;
b = t.b;
}
return *this;
} double Complex::getModulus()
{
return sqrt( a*a + b*b);
} double Complex::getA()
{
return a;
} double Complex::getB()
{
return b;
}

3.写测试文件test.cpp

#include "stdio.h"
#include "Complex.h" int main()
{
Complex t1(1,3);
Complex t2(2,6); Complex t3=t1+t2; printf("t3.a=%f t3.b=%f\n",t3.getA(),t3.getB()); printf("t3 Modulus:%f\n",t3.getModulus()); Complex t4=t3; printf("t4==t3: %d\n",t4==t3);
printf("t4!=t3: %d\n",t4!=t3);
printf("t3==t1: %d\n",t3==t1); return 0;
}

 

4.编译运行

t3.a=3.000000  t3.b=9.000000
t3 Modulus:9.486833
t4==t3: 1 //为真
t4!=t3: 0 //为假
t3==t1: 0 //为假

  

 

最新文章

  1. /boot/grub/device.map【设备映射】
  2. HTML5在VS2010中的智能提示
  3. 广播变量、累加器、collect
  4. Python数据类型-----数字&字符串
  5. 【python自动化第九篇:进程,线程,协程】
  6. 轻松搞定javascript变量(闭包,预解析机制,变量在内存的分配 )
  7. jenkins+maven +svn+tomcat7集群部署(一)
  8. 当@PathVariable遇上中文和点
  9. Linux中的apache的服务命令
  10. javaScript(1)---概述
  11. [Tensorflow实战Google深度学习框架]笔记4
  12. db2 OLAP函数使用
  13. vue项目使用webpack loader把px转换为rem
  14. oracle数据库数值类型
  15. BIO与NIO、AIO的区别(这个容易理解)
  16. JS冒泡排序的6种写法(武当雄风)
  17. VSCode开发(一)——入门基础
  18. Alamofire源码导读五:错误表示
  19. UVa 1374 Power Calculus (IDA*或都打表)
  20. salt 常用命令整理

热门文章

  1. C#: 以管理员权限运行包含有cd命令的.bat文件
  2. StriveEngine-UDP
  3. 解决 canvas 绘图在高清屏中的模糊问题
  4. Linux巩固记录(2) java项目的编译和执行
  5. WCF:wsdl
  6. swiper4-vue 不使用loop,由最后一张跳到第一张
  7. 课程二(Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization),第二周(Optimization algorithms) —— 2.Programming assignments:Optimization
  8. C#:VS2010 由于缺少调试目标"xx.exe",Visual Studio无法开始调试,请生成项目并重试,或者相应地设置OutputPath和AssemblyName属性,使其指向目标程序集的正确位置
  9. KMP算法的next函数求解和分析过程
  10. mysql基础知识(1)