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

目录
  • 1. C++运算符重载介绍
    • 1.1 单目运算符与双目运算符
    • 1.2 友元运算符
  • 2. 实例讲解
    • 2.1 头文件定义
    • 2.2 实现运算符重载
  • 总结

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运算符重载向量类重载内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解C++编程中的重载流插入运算符和流提取运算符

    C++的流插入运算符"<<"和流提取运算符">>"是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream.cin和cout分别是istream类和ostream类的对象.在类库提供的头文件中已经对"<<"和">>"进行了重载,使之作为流插入运算符和流提取运算符,能用来输出和输入C++标准类型的数据.因此,凡是用"cout&

  • C++ 中重载和运算符重载加号实现矩阵相加实例代码

     C++ 重载+运算符重载加号 实现矩阵相加 学习C++ 基础知识,这里实现简单的实例,记录下自己学习生活,很简单,大家一起看看吧! 实例代码: #include<iostream> #include<iomanip> using namespace std; class Complex { private: int i,j,n,a[2][3]; public: Complex(); Complex operator+(Complex &c); void display()

  • 详解C++编程中的单目运算符重载与双目运算符重载

    C++单目运算符重载 单目运算符只有一个操作数,如!a,-b,&c,*p,还有最常用的++i和--i等.重载单目运算符的方法与重载双目运算符的方法是类似的.但由于单目运算符只有一个操作数,因此运算符重载函数只有一个参数,如果运算符重载函数作为成员函数,则还可省略此参数. 下面以自增运算符"++"为例,介绍单目运算符的重载. [例] 有一个Time类,包含数据成员minute(分)和sec(秒),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算.要求输出分和秒的值. #

  • c++运算符重载基础知识详解

    实际上,很多C++运算符已经被重载.eg:将*运算符用于地址,将得到存储在这个地址中的值,将他用于2个数字时,得到的将是他们的乘积.C++根据操作数的数目和类型来决定采用哪种操作. C++允许将运算符重载扩展到用户定义的类型.例如,允许使用+将两个对象相加.编译器将根据操作数的数目和类型决定使用加法定义.运算符重载可以使代码看起来更自然.例如,将2个数组相加是一种常见的运算.通常,需要使用下面这样的for循环来实现: 复制代码 代码如下: for (int i = 0; i < 20; i++)

  • C++运算符重载的方法详细解析

    运算符重载实质上是函数的重载 重载运算符的函数一般格式如下: 函数类型    operator  运算符名称    (形参表列) {对运算符的重载处理} 例如,想将"+"用于Complex(复数)的加法运算,函数的原型可以是这样的: 复制代码 代码如下: Complex operator + (Complex & c1,Complex &c2); 其中,operator是关键字,时候专门用于定义重载运算符的函数的,运算符名称就是C++提供给用户的预定运算符. 注意:函数

  • C++运算符重载规则详解

    C++允许重载的运算符和不允许重载的运算符 C++中绝大部分的运算符允许重载,具体规定见表 不能重载的运算符只有5个: .  (成员访问运算符) .*  (成员指针访问运算符) ::  (域运算符) sizeof  (长度运算符) ?:  (条件运算符) 前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符和sizeof 运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征. C++运算符重载的规则 C++对运算符重载定义了如下几条规则. 1) C++不允许用户自己定义新的

  • C++运算符重载 成员函数与友元函数详解

    复制代码 代码如下: #include<iostream>using namespace std;class A{    int x,y;    public:    A(int xx,int yy):x(xx),y(yy){}    A(){x=0;y=0;}    A operator+(const A&b) //不加const限定,也可以    { return A(x+b.x,y+b.y); }    A operator-()    { return A(-x,-y); } 

  • C++中不能被重载的运算符介绍

    C/C++ 里大多数运算符都可以在 C++ 中被重载.C 的运算符中只有 . 和 ?:(以及 sizeof,技术上可以看作一个运算符)不可以被重载.C++ 增加了一些自己的运算符,除了 :: 和 .* 外,大多数都可以被重载.

  • C++重载运算符的规则详解

    (1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载.例如,有人觉得BASIC中用"* *"作为幂运算符很方便,也想在C++中将"* *"定义为幂运算符,用"3* *5"表示35,这是不行的. (2)C++允许重载的运算符C++中绝大部分运算符都是可以被重载的. 不能重载的运算符只有5个: .             (成员访问运算符) .*            (成员指针访问运算符) ::             (域运

  • 解析C++中不能重载为友元函数的四个运算符

    C++规定有四个运算符 =, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数),这是为什么呢?现在先说说赋值运算符"="的重载C++规定赋值运算符"="只能重载为类的非静态成员函数,而不可以重载为类的友元函数.不能重载为类的静态成员应该比较容易理解,因为静态成员函数是属于整个类的,不是属于某个对象的,它只能去操作类静态数据成员.而赋值运算符"="是基于对象操作的.那么为什么赋值运算符不可以重载为类的友元函数?像同样都是双目

随机推荐