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

函数重载

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

类中的函数重载

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

操作符重载(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 //为假

  

 

15.C++-操作符重载、并实现复数类的更多相关文章

  1. 15.C++-操作符重载

    首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...

  2. C++学习笔记15:操作符重载的函数原型列表(推荐)

    //普通四则运算 friend A operator +(const A & lhs, const A & rhs); friend A operator -(const A & ...

  3. [GeekBand] C++学习笔记(1)——以复数类为例

    本篇笔记以复数类(不含指针的类)为例进行面向对象的学习 ========================================================= 复数类的声明: class ...

  4. 5.1 C++基本操作符重载

    参考:http://www.weixueyuan.net/view/6379.html 总结: 操作符重载指的是将C++提供的操作符进行重新定义,使之满足我们所需要的一些功能. 长度运算符“sizeo ...

  5. C++解析(17):操作符重载

    0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...

  6. C++中操作符重载的概念

    1,下面的复数解决方案是否可行? 1,代码示例: class Comples { public: int a; int b; }; int main() { Complex c1 = {, }; Co ...

  7. C++ operator overload -- 操作符重载

    C++ operator overload -- 操作符重载 2011-12-13 14:18:29 分类: C/C++ 操作符重载有两种方式,一是以成员函数方式重载,另一种是全局函数. 先看例子 # ...

  8. C++ 操作符重载 (operator)

    重载不能改变操作符的优先级 如果一个内建操作符是一元的,那么所有对它的重载仍是一元的.如果是二元的重载后也是二元的 下面看一个有代表性的例子:: 头文件Complex.h: #includeusing ...

  9. C++ 数组操作符重载、函数对象分析、赋值操作符

    string类型访问单个字符 #include <iostream> #include <string> #include <sstream> using name ...

随机推荐

  1. bootstrap基础学习小记(三)网格简介

    网格系统:网格系统的实现原理非常简单,仅仅是通过定义容器大小,平分12份(也有平分成24份或32份,但12份是最常见的),再调整内外边距,最后结合媒体查询,就制作出了强大的响应式网格系统.Bootst ...

  2. 【VB.NET】通过 IPIP.NET 数据库来查询IP地址

    上一次介绍了利用纯真数据库查询IP地址详细信息的方法.然而纯真数据库是由网友反馈所提供的,很多数据描述并不准确,所以我上网找了一些其他的IP数据库,最后就找到了 ipip.net 这个网站所提供的IP ...

  3. ModelValidator基于元数据的验证

    ModelValidator主要是应用在ModelMetadata元数据的类型上或类型属性上.它是验证的基础类型,所有的ModelValidatorProviders.DataAnnotationVa ...

  4. centos下配置nginx遇到的一些基本的坑

    作为一个用.net的渣渣,常年混迹在window平台下,对Linux啥都不懂.随着.net core开源.跨平台后,也开始学习下linux. 在Desktop/Webs下放了一个index.html的 ...

  5. CentOS 7 - 配置服务实现开机自启动

    新建系统服务描述文件 cd /etc/systemd/system sudo vim myapp.service 添加以下配置: [Unit] # 这里添加你的服务描述 Description=mya ...

  6. Python3.5 学习十七

    jQuery 模块=类库 jQuery就是DOM .BOM.Javascript的封装成的类库 一.查找元素.DOM只有10种左右选择器 jQuery有很多选择器和筛选器 PS:jQuery 推荐1系 ...

  7. Linux系统用户与属组管理(3)

    好了,终于要到了管理 Linux 账号的时刻了,对于 Linux 有一定的熟悉度之后,再来就是要管理连上 Linux 的账号问题了,这个账号的问题可大可小,大到可以限制他使用 Linux 主机的各项资 ...

  8. poi 读取使用 Strict Open XML 保存的 excel 文档

    poi 读取使用 Strict Open XML 保存的 excel 文档 某项目有一个功能需要读取 excel 报表内容,使用poi读取时报错: 具体错误为: org.apache.poi.POIX ...

  9. linux(乌班图)下执行pip没有问题,执行sudo pip报错的问题

    最近刚装好linux的虚拟机,在装一个套件时提示权限不足,于是添加上了 sudo 命令,结果直接报以下错误, Traceback (most recent call last): File " ...

  10. POJ 2771

    #include <iostream> #include <string> #define MAXN 505 using namespace std; int _m[MAXN] ...