1. C++运算符重载介绍

 C ++ 中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C ++ 中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型执行特定的操作。运算符重载的实质是函数重载,它提供了C ++ 的可扩展性,也是C ++ 最吸引人的特性之一。

运算符重载时要遵循以下规则:

( 1 ) 除了类属关系运算符 " . " 、成员指针运算符 " .* " 、作用域运算符 " :: " 、sizeof运算符和三目运算符 " ?: " 以外,C ++ 中的所有运算符都可以重载。

( 2 ) 重载运算符限制在C ++ 语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。

( 3 ) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。

( 4 ) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。

( 5 ) 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。

( 6 ) 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。

1.1 单目运算符与双目运算符

( 1 ) 双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数。

比如说你重载+号,如果写在类外面,那么是需要两个参数的,而写在类里面,只能写一个参数,因为当这个函数被调用的时候,会自动的传一个this指针进去,就是对象本身,所以只需要一个参数

( 2 ) 前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数没有形参。

( 3 ) 后置单目运算符重载为类的成员函数时,函数要带有一个整型形参。

比如前置++,和后置++,带一个整形形参只是为了区分

1.2 友元运算符

有些运算符是一定得声明为友元的,比如<<,>>运算符

因为=,+这些运算符,是c++最基本的运算符,而>>,<<运算符是标准头文件里面的一个类里面写的,你不能把这个函数声明为你这个自定义类的函数,因为这是别人类里面的函数,因此你只能把它声明为友元函数,声明为友元函数之后,那么这个函数它就可以访问你这个自定义类里面的私有成员变量

2. 实例讲解

光看这些概念,想必没有接触过的同学头都大了,接下来我通过一个向量类的例子,来讲解一下各个运算符重载怎么用

2.1 头文件定义

这次我们来实例一个向量类,什么是向量类呢,就是数学里面的向量,一个括号,里面两个数字,看一下头文件你就明白啦

class Vec2D {
private:
double x_;
double y_; public: static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D(double x, double y) :x_(x), y_(y) {}
Vec2D() { x_ = 0.0; y_ = 0.0; } std::string toString(); friend Vec2D operator+(const Vec2D& v1, const Vec2D& v2);
friend Vec2D operator-(const Vec2D& v1, const Vec2D& v2);
friend double operator*(const Vec2D& v1, const Vec2D& v2);
friend Vec2D operator+(const Vec2D& v1, double num);
friend Vec2D operator*(const double num, const Vec2D& v2);
friend Vec2D operator*(const Vec2D& v2, const double num);
friend istream& operator>>(istream& stream, Vec2D& v1);
friend std::ostream& operator<<(std::ostream& stream, const Vec2D& v1); Vec2D negative(); Vec2D operator-(); Vec2D operator++();
Vec2D operator++(int dummy); Vec2D operator--(); Vec2D operator+=(const Vec2D& v);
Vec2D operator-=(const Vec2D& v); double& operator[](const int& index); double magnitude();
double direction();
int compareTo(Vec2D& v2); operator double(); double getX()const { return x_; }
double getY() const { return y_; }
void setX(double x) { x_ = x; }
void setY(double y) { y_ = y; }
};

可以看到,其实私有成员就是 x_和y_,然后我重载了非常多的函数,下面我们来看一下具体的实现

2.2 实现运算符重载

toString函数

这个函数我就不多说啦,比较简单

std::string Vec2D::toString()
{
std::string res = "(" + std::to_string(getX()) + ", " + std::to_string(getY()) + ")";
return res;
}

negative函数

这个函数是用来将向量变成负方向

Vec2D Vec2D::negative()
{
return Vec2D(-1 * x_, -1 * y_);
}

operator-函数

第一个重载函数出现了,是重载的符号,更加方便的实现了改变向量为负方向的操作

这样我们可以通过 -a,-b的形式来调用

Vec2D Vec2D::operator-()
{
return Vec2D(-1 * x_, -1 * y_);
}

operator++函数

这个函数是前置++运算符,返回*this就是返回当前对象

Vec2D Vec2D::operator++()
{
x_++;
y_++;
return *this;
}

operator++函数

这个函数是后置++运算符,所以后面加了一个类型的参数,这个参数唯一的意思是与前置++作区分

我们首先创建了一个临时变量,然后将本身的x,y加1,返回的却是临时变量,这样就实现了后置++的操作

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D Vec2D::operator++(int dummy)
{
Vec2D ret(x_, y_);
x_++;
y_++;
return ret;
}

operator--函数

减减同理,就是将x,y都减1

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D Vec2D::operator--()
{
x_ -= 1;
y_ -= 1;
return *this;
}

operator+= ,-=函数

这两个函数比较相似,我就放到一起讲啦,这里是将调用这个函数本身的对象,与参数里面的v相加或者相减

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D Vec2D::operator+=(const Vec2D& v)
{
x_ += v.x_;
y_ += v.y_;
return *this;
} Vec2D Vec2D::operator-=(const Vec2D& v)
{
x_ -= v.x_;
y_ -= v.y_;
return *this;
}

operator[ ]函数

这里重载了[ ],有一个参数,index,用来选择到底是返回x还是y

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
double& Vec2D::operator[](const int& index)
{
if (index == 0) {
return x_;
}
else if (index == 1) {
return y_;
}
else {
printf("subscript error\n");
exit(0);
}
}

operator+(类外)函数

因为是在类外重载,所以有两个参数,同时要注意将这个函数声明为友元函数,因为这样才可以访问私有成员变量

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
//类外重载,运算符重载函数作为类的友元函数
Vec2D operator+(const Vec2D& v1, const Vec2D& v2) {
Vec2D ret; ret.setX(v1.getX() + v2.getX());
ret.setY(v1.getY() + v2.getY()); return ret;
} Vec2D operator+(const Vec2D& v1, double num) {
Vec2D ret; ret.setX(v1.getX() + num);
ret.setY(v1.getY() + num); return ret;
}

operator*函数

这里重载了*,用来实现向量之间的相乘

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D operator*(const double num, const Vec2D& v2) {
Vec2D ret; ret.setX(num * v2.getX());
ret.setY(num * v2.getY()); return ret;
}

重载>> <<

这里给大家避个坑,一定要引入iostream头文件,而不是用using

这两个函数就是用来实现cout和cin

可以看到,实现cin 是通过 istream对象来实现的

实现cout 是通过ostream来实现的

记得在最后返回istream或者ostream对象

istream& operator>>(istream& stream, Vec2D& v1)
{
double x, y;
stream >> x >> y;
v1.setX(x);
v1.setY(y);
// 也可以直接
// stream >> x_ >> y_;
return stream;
} ostream& operator<<(ostream& stream, const Vec2D& v1)
{
std::string res = "(" + std::to_string(v1.getX()) + ", " + std::to_string(v1.getY()) + ")";
stream << res; return stream;
}

C++11运算符重载详解与向量类重载实例(<<,>>,+,-,*等)的更多相关文章

  1. 第7.11节 案例详解:Python类实例变量

    上节老猿介绍了实例变量的访问方法,本节结合一个具体案例详细介绍实例变量访问. 本节定义一个Vehicle类(车),它有三个实例变量self.wheelcount(轮子数).self.power(动力) ...

  2. STM32F103的11个定时器详解(转)

    源:STM32F103的11个定时器详解 STM32F103系列的单片机一共有11个定时器,其中:2个高级定时器4个普通定时器2个基本定时器2个看门狗定时器1个系统嘀嗒定时器 出去看门狗定时器和系统滴 ...

  3. CSS选择器详解(伪类) 转 http://blog.csdn.net/Panda_m/article/details/50084699

    CSS选择器详解 之 伪类 伪类对大小写不敏感 结构伪类选择器 结构伪类是CSS3新增的类型选择器,利用DOM树实现元素过滤,通过文档结构的相互关系来匹配元素,可以减少class和id属性的定义,使文 ...

  4. 详解javascript的类

    前言 生活有度,人生添寿. 原文地址:详解javascript的类 博主博客地址:Damonare的个人博客 Javascript从当初的一个"弹窗语言",一步步发展成为现在前后端 ...

  5. mybatis 详解(三)------入门实例(基于注解)

    1.创建MySQL数据库:mybatisDemo和表:user 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 2.建立一个Java工程,并导入相应的jar包,具体目录如 ...

  6. 详解 QT 主要类 QWidget

    QWidget类是所有用户界面对象的基类,每一个窗口部件都是矩形,并且它们按Z轴顺序排列的.一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住一部分. 先来看内容. AD: 2013云计算架构师 ...

  7. 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法

    第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法 上节介绍了Python中类的静态方法,本节将结合案例详细说明相关内容. 一.    案例说明 本节定义了类Sta ...

  8. c/c++面试题(6)运算符重载详解

    1.操作符函数: 在特定条件下,编译器有能力把一个由操作数和操作符共同组成的表达式,解释为对 一个全局或成员函数的调用,该全局或成员函数被称为操作符函数.该全局或成员函数 被称为操作符函数.通过定义操 ...

  9. C++运算符重载详解

    1.什么是运算符重载 运算符重载是一种函数重载. 运算符函数的格式:operatorop(argument-list)例如,operator+()重载+运算符.其中的op,必须是有效的C++运算符,如 ...

随机推荐

  1. 大数据学习之路—环境配置——IP设置(虚拟机修改Ip的内在原因及实现)

    一.IP原理 关于IP我的理解, (1)主要去理解IP地址的作用,IP地址包括网络相关部分和主机的相关部分.即:用一段特殊的数据,来标识网络特征和主机的特征. 至于具体的技术实现,日后可以慢慢体会和了 ...

  2. mysql数据库-运维合集

    目录 RDBMS 术语 整删改查操作 库操作 表操作 账号与授权 匹配符(条件查询) MySQL三大类数据类型 函数 其他操作 查看数据库的占用空间大小 开启慢查询 状态查询 字符集设置 忘记密码重置 ...

  3. 3. servlet 和 springmvc框架关系

    在springmvc上我们会编写很多相关的配置 编写springmvc.xml 配置映射器 配置 处理适配器 ... web.xml 配置前端控制器 (DispatcherServlet) 官网: h ...

  4. 【进阶之路】多线程条件下分段处理List集合的几种方法

    这两个月来因为工作和家庭的事情,导致一直都很忙,没有多少时间去汲取养分,也就没有什么产出,最近稍微轻松了一点,后续的[进阶之路]会慢慢回到正轨. 开门见山的说,第一次接触到多线程处理同一个任务,是使用 ...

  5. [leetcode] 68. 文本左右对齐(国区第240位AC的~)

    68. 文本左右对齐 国区第240位AC的~我还以为坑很多呢,一次过,嘿嘿,开心 其实很简单,注意题意:使用"贪心算法"来放置给定的单词:也就是说,尽可能多地往每行中放置单词. 也 ...

  6. Jmeter- 笔记10 - 在GUI生成html报告

    步骤1.在聚合报告,浏览一个存放jtl文件的路径,输入不存在的jtl文件,确定后会出现如下图弹窗,不用理会,关掉 步骤2.运行脚本 步骤3.打开工具 -> Generate HTML repor ...

  7. 4D毫米波雷达Radar

    4D毫米波雷达Radar 围绕雷达.激光雷达.高精定位等新一代传感器技术将会进入量产周期. 自动驾驶公司的竞争,在传感器配置上坦白说并没有太多差异化.除了车载激光雷达属于近几年的产物,类似摄像头.毫米 ...

  8. 03:CSS(01)

    内容概要 分组与嵌套 伪类选择器 伪元素选择器 选择器优先级 css属性相关(操作标签样式) 浮动 定位 模态框 透明度 内容详细 分组与嵌套 div,p,span { /*逗号表示并列关系*/ co ...

  9. DHCP:IP 并非与生俱来

    初识 DHCP 众所周知,因特网上的每台设备都规定了其全世界唯一的地址,也就是说 "IP 地址",正是由于有了 IP 地址,才保证了用户在连网的计算机上操作时,能够高效而且方便地从 ...

  10. 浅谈.Net Core中使用Autofac替换自带的DI容器

    为什么叫 浅谈 呢?就是字面上的意思,讲得比较浅,又不是不能用(这样是不对的)!!! Aufofac大家都不陌生了,说是.Net生态下最优秀的IOC框架那是一点都过分.用的人多了,使用教程也十分丰富, ...