重载运算符详解

重载运算符详解

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 ;
}
相关推荐
大福是小强2 天前
002-Kotlin界面开发之Kotlin旋风之旅
kotlin·函数式编程·lambda·语法·运算符重载·扩展函数
王老师青少年编程3 天前
CSP/信奥赛C++完整学习规划(价值2万的csp-j完整课程体系)
数据结构·c++·算法·语法·csp·信奥赛
深度混淆4 天前
《C#语法一篇通》,20万字,48小时阅读,持续完善中。。。
开发语言·c#·语法·入门教程
Freak嵌入式2 个月前
全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数
java·开发语言·人工智能·redis·python·语法
xiangshangdemayi2 个月前
WebGL系列教程八(GLSL着色器基础语法)
webgl·基础·shader·着色器·语法·glsl
骅青3 个月前
培训第二十三天(mysql主从脚本与mysql详细语句介绍)
数据库·mysql·脚本·语法
猫天意3 个月前
ESlint | 通过VsCode中的ESLint插件来实现自动修正语法错误
ide·vscode·编辑器·eslint·语法
EleganceJiaBao4 个月前
【C语言】《回调函数》详细解析
c语言·开发语言·关键字·语法·回调函数·详解
EleganceJiaBao4 个月前
【C语言】标识符大通关!
c语言·开发语言·javascript·标识符·关键字·语法·类型
鲁鲁5174 个月前
梧桐数据库:语法分析模块概述
优化·语法·查询·语法分析·梧桐数据库