C++11运算符重载和向量类重载实例详解(<<,>>,+,-,*等)

 更新时间:2021年07月15日 11:57:53   作者:进击的汪sir  
这篇文章主要给大家介绍了关于C++11运算符重载和向量类重载的相关资料,主要包括<<,>>,+,-,*等,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

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运算符重载和向量类重载的文章就介绍到这了,更多相关C++11运算符重载向量类重载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用代码验证linux子进程与父进程的关系

    使用代码验证linux子进程与父进程的关系

    Linux下父进程可以使用fork 函数创建子进程,但是当父进程先退出后,子进程会不会也退出呢?通过下面这个小实验,我们能够很好的看出来
    2014-02-02
  • C语言中求解图形的问题

    C语言中求解图形的问题

    这篇文章主要介绍了C语言中求解图形的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C语言实现循环单链表的示例代码

    C语言实现循环单链表的示例代码

    这篇文章主要给大家详细介绍了C语言如何实现循环单链表,文章通过代码示例讲解的非常详细,对我们的学习或工作有一定的参考价值,感兴趣的小伙伴跟着小编一起来看看吧
    2023-08-08
  • C++冒泡排序及其优化算法

    C++冒泡排序及其优化算法

    这篇文章主要为大家介绍了C++冒泡排序及其优化算法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11
  • C语言实现简单弹跳球游戏

    C语言实现简单弹跳球游戏

    这篇文章主要为大家详细介绍了C语言实现简单弹跳球游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • pcre函数详细解析

    pcre函数详细解析

    PCRE提供了19个接口函数,为了简单介绍,使用PCRE内带的测试程序(pcretest.c)示例用法
    2013-09-09
  • C++入门之内存处理详解

    C++入门之内存处理详解

    这篇文章主要为大家介绍了C++入门之内存处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • C++实现双向起泡排序算法

    C++实现双向起泡排序算法

    这篇文章主要为大家详细介绍了如何利用C++实现双向起泡排序算法,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以尝试一下
    2022-11-11
  • C++11如何实现无锁队列

    C++11如何实现无锁队列

    这篇文章主要介绍了C++11如何实现无锁队列,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • C++中命名空间(namespace)详解及其作用介绍

    C++中命名空间(namespace)详解及其作用介绍

    考虑一种情况,当我们有两个同名的人,Zara,在同一个班里。当我们需要对它们进行区分我们必须使用一些额外的信息和它们的名字,比如它们生活在不同的区域或者兴趣爱好什么的,在C++程序中也会遇到同样的情况,所以命名空间就此产生
    2022-08-08

最新评论