运算符重载

运算符重载的概念

运算符重载类似于函数重载。

运算符重载允许把标准运算符(如+-*<等)应用于定制数据类型的对象。

什么情况下需要考虑运算符重载?
需要用运算符操作自定义类的对象时,如对象之间直观自然,可以提高比较大小等,通过重载支持类的运算。

运算符重载:①体现了程序的可读性;②体现了C++的可扩充性

运算符重载的定义

作为类的成员函数或友元函数、作为一般函数(很少用)。

1、成员函数原型的格式:
函数类型 operator 运算符(参数表);
成员函数定义的格式:

函数类型 类名::operator 运算符(参数表)
{函数体;
}

以成员函数的方式重载运算符
-单目运算符:不带参数,该类对象为唯一操作数
-双目运算符:带一个参数,该类对象为左操作数、参数为右操作数

2、友元函数原型的格式:
friend 函数类型 operator 运算符(参数表);
友元函数定义的格式:

函数类型 operator 运算符(参数表)
{函数体;
}

以友元函数的方式重载运算符
-单目运算符:带一个参数,该参数为唯一操作数,是自定义类的对象 ++(a)
-双目运算符:带两个参数,第一个参数为左操作数、第二个参数为右操作数,至少有一个参数为自定义类的对象
+(a, b)

实例

#include <iostream>
using namespace std;class Complex
{public:Complex(double = 0.0, double = 0.0);Complex operator+(const Complex&) const;Complex Add(const Complex&) const;Complex operator-(const Complex&) const;Complex& operator=(const Complex&);void print() const;
private:double real;       // real partdouble imaginary;  // imaginary part
};
Complex::Complex(double r, double i)
{real = r;imaginary = i;
}
Complex Complex::operator+(const Complex &operand2) const
{Complex sum;sum.real = this->real + operand2.real;sum.imaginary= this->imaginary + operand2.imaginary;return sum;
}
Complex Complex::Add(const Complex &operand2) const
{//功能的实现同上
}
Complex Complex::operator-(const Complex &operand2) const
{Complex diff;diff.real = real - operand2.real;diff.imaginary=imaginary - operand2.imaginary;return diff;
}
Complex& Complex::operator=(const Complex &right)
{real = right.real;imaginary = right.imaginary;return *this;   // enables concatenation
}
void Complex::print() const
{cout<<'('<<real<< "," << imaginary << ')';
}
int main()
{Complex x, y(4.3, 8.2), z(3.3, 1.1);cout << "x: "; x.print();cout << "\ny: ";  y.print();cout << "\nz: ";  z.print();x = y + z;  //比表达式x=y.Add(z);更简练,更直观cout << "\n\nx = y + z:\n";   x.print();cout << " = ";       y.print();cout << " + ";       z.print();return 0;
}

执行结果:

x: (0,0)
y: (4.3,8.2)
z: (3.3,1.1)x = y + z:
(7.6,9.3) = (4.3,8.2) + (3.3,1.1)

运算符重载的规则

①运算符重载不允许发明新的运算符。

②不能改变运算符操作对象的个数。

③运算符被重载后,其优先级和结合性不会改变。

④不能重载的运算符:

一元运算符重载

操作数是自定义类的对象或对象的引用。

作为成员函数重载没有参数。

作为友元函数重载参数为自定义类的对象或对象的引用(概念介绍)。

实例

(成员函数的方式重载!)

#include <iostream>**自增、自减运算符重载**
#include <string.h>
using namespace std;class CString
{public:CString(const char *s="");CString(const CString& s);~CString();CString& operator = (const CString& s);CString& operator = (const char *s);bool operator !();char *m_str;
private:int m_size;
};
CString::CString(const CString& s)
{m_size=strlen(s.m_str);m_str=new char[m_size+1];strcpy(m_str,s.m_str);
}
CString::CString(const char *s/* ="" */)
{m_size=strlen(s);m_str=new char[m_size+1];strcpy(m_str,s);
}
bool CString::operator !()
{if (strlen(m_str)==0){return true;}elsereturn false;
}
CString::~CString()
{delete []m_str;
}
int main()
{CString s1, s2("some string");if (!s1)//括号中等价于s1.operator!()=>显示调用cout<<"s1 is NULL!"<<endl;else   cout<<"s1 is not NULL!"<<endl;if (!s2)cout<<"s2 is NULL!"<<endl;elsecout<<"s2 is not NULL!"<<endl;return 0;
}

执行结果:

s1 is NULL!
s2 is not NULL!

自增、自减运算符重载

在C++中,单目运算符有++和- -,它们是变量自动增1和自动减1的运算符。在类中可以对这两个单目运算符进行重载。

前置自增和前置自减的重载:
1、成员函数的方式重载,原型为:
函数类型 & operator++();
函数类型 & operator--();
2、友元函数的方式重载,原型为:
函数类型 & operator++(类类型 &);
函数类型 & operator--(类类型 &);

后置自增和后置自减的重载:
1、成员函数的方式重载,原型为:
函数类型 operator++(int);
函数类型 operator--(int);
2、友元函数的方式重载,原型为:
函数类型 operator++(类类型 &,int);
函数类型 operator--(类类型 &,int);

使用前缀运算符的语法格式:++<对象>;
使用后缀运算符的语法格式:<对象>++;

实例

#include <iostream>
using namespace std;class  CInt
{public:CInt(int a=0);void Print();CInt &operator ++();CInt  operator ++(int);
private:int i;
};
CInt::CInt (int  a)
{i = a;
}
void CInt::Print()
{cout << "i=" << i << endl;
}
CInt &CInt::operator ++()
{++i;return *this;
}
CInt  CInt::operator ++(int)
{CInt sum;sum=*this;++i;return sum;
}
int main(void)
{CInt  a(5), b(5), c, d;c = a++;d = ++b;cout << "a: ";a.Print();cout << "b: ";b.Print();cout << "c: ";c.Print();cout << "d: ";d.Print();return 0;
}

执行结果:

a: i=6
b: i=6
c: i=5
d: i=6

二元运算符重载

1、成员函数的方式重载二元运算符
函数原型:
函数类型 operator 二元运算符(类型 参数);
带有一个参数
左操作数必须为该类的对象或对象的引用

2、二元运算符重载为带有两个参数的非成员函数
函数原型:
函数类型 operator 二元运算符(类型 参数1,类型 参数2);
参数之一必须是类的对象或对象的引用

赋值运算符的重载

1、赋值运算符可直接用在自定义类的对象赋值。

2、如果没有提供重载的赋值运算符函数来复制类的对象。编译器就会提供默认版本的operator=()

3、赋值运算符的默认版本会简单地进行逐个成员的复制过程,类似于默认的拷贝构造函数。

4、运算符“=”重载时,要检查两个操作数是否为同一个对象。

5、如果对象中包含动态分配的空间,这种赋值方式就不合适了,如:

CString s1("abc"), s2("def");  //具体类见一元运算符重载实例
s1 = s2;

赋值的结果是:对象s1和s2的指针str都指向了同一块数据空间。

6、对象中包含动态分配的空间,赋值运算符需要自己重载,函数实现的算法与拷贝构造函数类似。

实例

#include <iostream>
#include <string.h>
using namespace std;class CString
{public:CString(const char *s="");CString(const CString& s);CString & operator = (const CString & s);CString & operator = (const char *s);char *m_str;
private:int m_size;
};
CString::CString(const CString& s)
{m_size=strlen(s.m_str);m_str=new char[m_size+1];strcpy(m_str,s.m_str);
}
CString::CString(const char *s/* ="" */)
{m_size=strlen(s);m_str=new char[m_size+1];strcpy(m_str,s);
}
CString& CString::operator =(const CString& str)
{if (this!=&str){delete[] m_str;m_size=strlen(str.m_str);m_str=new char[m_size+1];strcpy(m_str,str.m_str);}return *this;
}
CString& CString::operator =(const char *str)
{delete[] m_str;m_size=strlen(str);m_str=new char[m_size+1];strcpy(m_str,str);return *this;//为什么需要返回值?
}
int main()
{CString s1("abc"),s2(s1),s3;s3=s2;cout<<"s1:"<<s1.m_str<<endl;  //m_str应该声明成私有,如何输出cout<<"s2:"<<s2.m_str<<endl;  //cout<<s2;cout<<"s3:"<<s3.m_str<<endl;s3="tom";cout<<"s3:"<<s3.m_str<<endl;return 0;
}

执行结果:

s1:abc
s2:abc
s3:abc
s3:tom

‘+’运算符重载的使用

实例

#include <iostream>
#include <string.h>
#include <windows.h>
using namespace std;class CString
{public:CString(const char *s="");CString(const CString& s);CString  operator + (const CString &s);CString  operator + (const char *s);CString & operator = (const CString & s);CString & operator = (const char *s);char *m_str;
private:int m_size;
};
CString::CString(const CString& s)
{m_size=strlen(s.m_str);m_str=new char[m_size+1];strcpy(m_str,s.m_str);
}
CString::CString(const char *s/* ="" */)
{m_size=strlen(s);m_str=new char[m_size+1];strcpy(m_str,s);
}
CString CString::operator+(const CString &s)
{CString tempStr;char *p=new char[strlen(this->m_str)+strlen(s.m_str)+1];if(p==NULL){exit(1);}strcpy(p,this->m_str);strcat(p,s.m_str);tempStr.m_str=p;return tempStr;
}
CString CString::operator+(const char *s)
{CString tempStr;char *p=new char[strlen(this->m_str)+strlen(s)+1];strcpy(p,this->m_str);strcat(p,s);tempStr.m_str=p;return tempStr;
}
CString& CString::operator =(const CString& str)
{if (this!=&str){delete[] m_str;m_size=strlen(str.m_str);m_str=new char[m_size+1];strcpy(m_str,str.m_str);}return *this;
}
CString& CString::operator =(const char *str)
{delete[] m_str;m_size=strlen(str);m_str=new char[m_size+1];strcpy(m_str,str);return *this;
}
int main()
{CString s1="hello",s2("world"),s3;s3=s1+s2;cout<<"s3 = s1+s2 -- "<<s3.m_str<<endl;s3=s3+"abc"; //s3="abc"+s1; //会出现什么问题?? =>会报错:no match for 'operator+' in '"abc" + s1'cout<<"s3:"<<s3.m_str<<endl;return 0;
}

执行结果:

s3 = s1+s2 -- helloworld
s3:helloworldabc

重载运算符‘[ ]’

实例

#include <iostream>
#include <string.h>
#include <windows.h>
using namespace std;class CString
{public:CString(const char *s="");CString(const CString& s);char operator [](int index);int GetSize();char *m_str;
private:int m_size;
};
CString::CString(const CString& s)
{m_size=strlen(s.m_str);m_str=new char[m_size+1];strcpy(m_str,s.m_str);
}
CString::CString(const char *s/* ="" */)
{m_size=strlen(s);m_str=new char[m_size+1];strcpy(m_str,s);
}
inline int CString::GetSize()
{return m_size;
}
char CString:: operator [](int index)
{if(index<0 || index>=m_size){//下标越界}return m_str[index];
}
int main()
{CString entry("extravagant");for(int i = 0;i<entry.GetSize();++i){cout<<"entry = "<<entry[i]<<endl;}return 0;
}

执行结果:

entry = e
entry = x
entry = t
entry = r
entry = a
entry = v
entry = a
entry = g
entry = a
entry = n
entry = t

复习笔记(六)——C++运算符重载(难点)相关推荐

  1. C++学习笔记:(四)运算符重载 类型转换

    目录 6.运算符重载 6.1运算符重载的基本概念 6.2成员函数重载运算符 6.3友元函数重载运算符 6.4成员函数重载运算符和友元函数重载运算符比较 6.5类型转换 6.运算符重载 面向对象程序设计 ...

  2. 【C++学习笔记四】运算符重载

    当调用一个重载函数和重载运算符时,编译器通过把您所使用的参数类型和定义中的参数类型相比较,巨鼎选用最合适的定义.(重载决策) 重载运算符时带有特殊名称的函数,函数名是由关键字operator和其后要重 ...

  3. python vector_[流畅的Python]读书笔记之十三运算符重载

    运算符重载 Python 关于运算符重载的规则: 不能重载内置类型的运算符 不能新建,只能重载 某些运算符不能重载--is.and.or 和 not 一元运算符 __neg__ __pos__ __i ...

  4. JavaScript学习笔记:JS运算符重载

    1.定义   在了解运算符重载之前,先了解一下重载.重载是指可使函数.运算符等处理不同类型数据或者接受不同个数参数的一种方法.   函数重载是指函数名相同,函数参数个数或者参数类型不同,以至于返回类型 ...

  5. 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)

    0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...

  6. (C++学习笔记七)运算符重载

    九.运算符重载 1.Code : #include<iostream> using namespace std;//运算符重载的意义: //对已有的 运算符 重新进行定义,赋予其另一项功能 ...

  7. c++复习(2)拷贝构造函数与运算符重载

    目录 前言 拷贝构造函数 函数定义 调用 缺省(默认)的拷贝构造函数 -- 浅拷贝 涉及指针或者内存操作 用char * 用char[] 用string 自己写的拷贝构造函数 类中数据含有指针 类中含 ...

  8. 《信息与编码》考试复习笔记6----第六章连续信源熵和信道容量(考点在连续信道容量)

    系列文章链接目录 一.<信息与编码>考试复习笔记1----第一章概论 二.<信息与编码>考试复习笔记2----第二章离散信息源 三.<信息与编码>考试复习笔记2-- ...

  9. c++重载运算符_C/C++编程笔记:运算符重载丨重载C++中的New和Delete运算符

    new和delete运算符也可以像C ++中的其他运算符一样重载.New和Delete运算符可以全局重载,也可以在特定类中重载. (1)如果使用某个类的成员函数来重载这些运算符,则意味着这些运算符仅针 ...

最新文章

  1. linux stat函数讲解
  2. USTC English Club Note20211108
  3. bootstrap布局两列或者多列表单
  4. [渝粤教育] 宁波大学 聆听中国 参考 资料
  5. 修改服务器时间需要重启吗,云服务器需要定期重启吗
  6. 解决问题的能力 > 10倍程序员
  7. Linux系统初学者指南,Linux系统新手入门指南(二)
  8. 如何在CSDN中免费下载资料
  9. 怎样写工科研究生论文
  10. Java小白必看:开发一个编程项目的完整流程(附100套Java编程项目源码+视频)
  11. 经纬度(度分秒)坐标转换为小数格式(weixin公众号【图说GIS】)
  12. PostmanCn: Postman中文版
  13. markdown文本居中
  14. dacom蓝牙耳机怎么重置_无线蓝牙耳机 常见八大故障解决办法
  15. Github Actions实现自定义编译OpenWRT固件和第三方插件
  16. gentoo linux 内核,手动升级Gentoo及其内核的方法
  17. Think On Paper
  18. 博客上怎么根据搜索ID搜索其它人
  19. 软碟通 (UltraISO)制作启动盘
  20. 时间类型转换的问题“2021-01-20T10:09:11Z”

热门文章

  1. iphone屏蔽系统更新_未越狱屏蔽系统更新还是来了
  2. 112. Leetcode 673. 最长递增子序列的个数 (动态规划-子序列问题)
  3. 29. Leetcode 19. 删除链表的倒数第 N 个结点 (链表-双指针)
  4. 13. Leetcode 349. 两个数组的交集 (数组-分离双指针)
  5. pytorch模型的保存与加载
  6. TensorFlow 安装protoc
  7. 背景和文字分离的matlab实现
  8. java带参数的构造方法_崤云说 | JAVA面向对象
  9. 35+ Top Apache Tomcat Interview Questions And Answers【转】
  10. Kafka设计解析(七)- 流式计算的新贵 Kafka Stream