重载运算符详解

重载运算符详解

1.概念

运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能。这个函数叫做运算符重载函数(常为类的成员函数)。   用函数的方式实现了(+ - * / []数组 && || 逻辑 等)运算符的重载。根据需求决定重载那些运算符,用到的时候再百度案例即可。

2.运算符重载的基本格式

返回值类型 类名::operator重载的运算符(参数表)    {    ......    }

operator是关键字,它与重载的运算符一起构成函数名。

3.运算符重载的两种方法

二元运算符重载

1.类内重载

复制代码
#include <iostream>
using namespace std;
​
class Point{
public:
    Point(){};
    Point (int x, int y): x(x),y(y) {};
    Point operator+(const Point &b){ //类内重载,运算符重载函数作为类的成员函数
        Point ret;
        ret.x = this->x + b.x;
        ret.y = this->y + b.y;
        return ret;
   }
    int x,y;
};
​
int main() {
    Point a(2,4),b(5,3);
    Point c = a + b;      //这里c++编译器会,自动去找 + 运算符的重载函数
 cout<< "x :" << c.x << endl;
    cout<<"y :" << c.y << endl;
}
12345678910111213141516171819202122

运行结果:x : 7     y : 7

重点:运算符重载是类内重载时,运算符重载函数作为类的成员函数,以上述代码为例 a + b 相当于 a 对象调用+方法并且传入参数时 b 对象。

2.类外重载(用友元函数的方法实现)

复制代码
#include <iostream>
using namespace std;
​
class Point{
public:
    Point(){};
    Point (int x, int y): x(x),y(y) {};
    friend Point operator+(const Point &, const Point &);   //声明类的友元函数
    int x,y;
};
​
Point operator+(const Point &a,const Point &b){//类外重载,运算符重载函数作为类的友元函数
    Point ret;
    ret.x = a.x + b.x;
    ret.y = a.y + b.y;
    return ret;
}
​
int main() {
     Point a(2,4),b(5,3);
    Point c = a + b;
 cout<< "x :" << c.x << endl;
    cout<<"y :" << c.y << endl;
}
123456789101112131415161718192021222324

一元运算符重载(注意:返回值当左值得时候,返回的是一个引用)

1.插入运算符重载>> and 提取运算符重载<<   以提取运算符重载<<为例,cout 是 ostream 类的对象。ostream 类和 cout 都是在头文件 中声明的。ostream 类将<<重载为成员函数。

下面我们重载 << 使用cout输出a对象

复制代码
#include <iostream>
using namespace std;
​
class Point{
public:
    Point(){};
    Point (int x, int y): x(x),y(y) {};
    friend ostream &operator<<(ostream &out , const Point &a);  //因为 << 是C++提供的类,我们无法访问,只能用友元函数。
private:
    int x,y;
};
​
//<< 运算符重载的函数实现   ostream是输入输出流的类
ostream &operator<<(ostream &out , const Point &a){
    out << "<Point>( " << a.x << ", " << a.y << ")";
    return out;
}
​
int main() {
​
    cout << c<< endl;    //直接输出类会报错,需要上面的 << 运算符重载
}

输出结果:< Point>( 7, 7) 重点:另外应该会有人对ostream &operator<<(ostream &out , const Point &a)函数感到疑惑,首先在重载<<时,返回值类型是ostream&, 第一个参数也是ostream& 。也就是说,表达式cout<<c的返回值仍是 cout,所以cout<<c<<endl;才能成立。

2.前置运算符重载++ and 后置运算符重载++ 重点:为区别前置和后置运算符,C++编译器要求,需要在后置运算符重载函数中加参数"int",这个类型在此除了以示区别之外并不代表任何实际含义;如果不加,编译器无法区分是前置++,还是后置++,导致报错。

复制代码
#include <iostream>
using namespace std;
​
class Point{
public:
    Point(){};
    Point (int x, int y): x(x),y(y) {};
    friend Point operator+(const Point &, const Point &);
    friend ostream &operator<<(ostream &out , const Point &a);
    Point& operator++(){ //前置++运算符,需要引用返回,不需要参数。返回自增后的值,且返回的是一个左值 
        this->x ++;
        this->y ++;
        return *this;
   }
     //const 修饰返回值不能修改  
    const Point operator++(int){//后置++,不需要引用返回,需要参数区分。返回自增前的值,且返回的是一个右值
        Point temp(x,y);       //因为后置++,是先使用,后自++,所以这里要保存一个临时值,再++,返回的是临时值。
        this->x ++;
        this->y ++;
        return temp;
   }
private:
    int x,y;
};
​
Point operator+(const Point &a,const Point &b){
    Point ret;
    ret.x = a.x + b.x;
    ret.y = a.y + b.y;
    return ret;
}
​
ostream &operator<<(ostream &out , const Point &a){
    out << "<Point>(" << a.x << " , " << a.y << ")";
    return out;
}
​
​
int main() {
    Point a(2,4),b(5,3);
    Point c = a + b;
    cout << c << endl;
    c++;
    cout << c << endl;
    ++c;
    cout << c << endl;
}

3.=等号运算符重载 C++中,对类对象进行操作时,我们就不能只是简简单单地,对类对象用=进行操作。 当我们没有自己设计等号运算符的重载函数,编译器会自动生成一个浅拷贝的赋值运算符的重载函数。 浅拷贝:只是简单地将一个对象的内存数据赋值给另一个对象,如果这个对象成员变量引用了外部资源时(new),那么这两个对象的成员变量都指向这个空间,当这两个对象生存周期结束时,进行析构,那么就会崩溃,对同一块内存我们delete了两次。

复制代码
#include <iostream>
using namespace std;
​
class  Name
{
public:
​
    //main函数中的问题   Name obj2 = obj1;  
 //解决方案: 手工的编写拷贝构造函数 使用深copy
 Name(const Name& obj)
 {
  m_len = obj.m_len;
  m_p = (char *)malloc(m_len + 1);
  strcpy(m_p, obj.m_p);
 }
​
   //等号运算符重载函数
 Name& operator=(Name &obj)  
 {
  //1.先释放旧的内存
  if (this->m_p != NULL)
  {
   delete[] m_p;
   m_len = 0;
  }
  //2.根据obj分配内存大小
  this->m_len = obj.m_len;
  this->m_p = new char [m_len+1]; //加1,结束符'\n'。
  
  //3.把obj赋值
  strcpy(m_p, obj.m_p);  //字符串的拷贝函数
  return *this;
 }
 
 ~Name()    //析构函数
 {
  if (m_p != NULL)
  {
   free(m_p);
   m_p = NULL;
   m_len = 0;
  }
 }
protected:
private:
 char *m_p ;
 int m_len; 
};
​
void main()
{
​
 Name obj1("abcdefg");
 Name obj2 = obj1;  //C++编译器提供的 默认的copy构造函数 浅拷贝,需要手工编写构造函数
 Name obj3("obj3");
​
 obj1 = obj2 = obj3;    //调用等号运算符重载
 cout<<"hello..."<<endl;
 system("pause");
 return ;
}
相关推荐
gis分享者5 天前
如何在 Shell 脚本中如何使用条件判断语句?(中等)
面试·shell·脚本·语法·使用·判断·条件
Mysticbinary8 天前
原始类型与泛型对比笔记
语法
缘三水14 天前
【C语言】17.字符函数和字符串函数
c语言·开发语言·语法
小李不困还能学15 天前
markdown语法以及快捷键大全
markdown·语法
缘三水15 天前
【C语言】16.指针(6)进阶篇目——数组与指针笔试题目详解
c语言·开发语言·指针·语法
缘三水16 天前
【C语言】15.指针(5)
c语言·开发语言·指针·语法
缘三水17 天前
【C语言】14.指针(4)
c语言·开发语言·指针·语法
缘三水18 天前
【C语言】13.指针(3)
c语言·开发语言·指针·语法
缘三水22 天前
【C语言】10.操作符详解(下)
c语言·开发语言·c++·语法·基础定义
WebGoC开发者1 个月前
GoC题解(22) GoC测试模拟题(2017.3.23)第6题:同心圆
经验分享·青少年编程·入门·语法·goc