复习笔记(六)——C++运算符重载(难点)
运算符重载
运算符重载的概念
运算符重载类似于函数重载。
运算符重载允许把标准运算符(如+
、-
、*
、<
等)应用于定制数据类型的对象。
什么情况下需要考虑运算符重载?
需要用运算符操作自定义类的对象时,如对象之间直观自然,可以提高比较大小等,通过重载支持类的运算。
运算符重载:①体现了程序的可读性;②体现了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++运算符重载(难点)相关推荐
- C++学习笔记:(四)运算符重载 类型转换
目录 6.运算符重载 6.1运算符重载的基本概念 6.2成员函数重载运算符 6.3友元函数重载运算符 6.4成员函数重载运算符和友元函数重载运算符比较 6.5类型转换 6.运算符重载 面向对象程序设计 ...
- 【C++学习笔记四】运算符重载
当调用一个重载函数和重载运算符时,编译器通过把您所使用的参数类型和定义中的参数类型相比较,巨鼎选用最合适的定义.(重载决策) 重载运算符时带有特殊名称的函数,函数名是由关键字operator和其后要重 ...
- python vector_[流畅的Python]读书笔记之十三运算符重载
运算符重载 Python 关于运算符重载的规则: 不能重载内置类型的运算符 不能新建,只能重载 某些运算符不能重载--is.and.or 和 not 一元运算符 __neg__ __pos__ __i ...
- JavaScript学习笔记:JS运算符重载
1.定义 在了解运算符重载之前,先了解一下重载.重载是指可使函数.运算符等处理不同类型数据或者接受不同个数参数的一种方法. 函数重载是指函数名相同,函数参数个数或者参数类型不同,以至于返回类型 ...
- 笔记②:牛客校招冲刺集训营---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 友元 友 ...
- (C++学习笔记七)运算符重载
九.运算符重载 1.Code : #include<iostream> using namespace std;//运算符重载的意义: //对已有的 运算符 重新进行定义,赋予其另一项功能 ...
- c++复习(2)拷贝构造函数与运算符重载
目录 前言 拷贝构造函数 函数定义 调用 缺省(默认)的拷贝构造函数 -- 浅拷贝 涉及指针或者内存操作 用char * 用char[] 用string 自己写的拷贝构造函数 类中数据含有指针 类中含 ...
- 《信息与编码》考试复习笔记6----第六章连续信源熵和信道容量(考点在连续信道容量)
系列文章链接目录 一.<信息与编码>考试复习笔记1----第一章概论 二.<信息与编码>考试复习笔记2----第二章离散信息源 三.<信息与编码>考试复习笔记2-- ...
- c++重载运算符_C/C++编程笔记:运算符重载丨重载C++中的New和Delete运算符
new和delete运算符也可以像C ++中的其他运算符一样重载.New和Delete运算符可以全局重载,也可以在特定类中重载. (1)如果使用某个类的成员函数来重载这些运算符,则意味着这些运算符仅针 ...
最新文章
- linux stat函数讲解
- USTC English Club Note20211108
- bootstrap布局两列或者多列表单
- [渝粤教育] 宁波大学 聆听中国 参考 资料
- 修改服务器时间需要重启吗,云服务器需要定期重启吗
- 解决问题的能力 > 10倍程序员
- Linux系统初学者指南,Linux系统新手入门指南(二)
- 如何在CSDN中免费下载资料
- 怎样写工科研究生论文
- Java小白必看:开发一个编程项目的完整流程(附100套Java编程项目源码+视频)
- 经纬度(度分秒)坐标转换为小数格式(weixin公众号【图说GIS】)
- PostmanCn: Postman中文版
- markdown文本居中
- dacom蓝牙耳机怎么重置_无线蓝牙耳机 常见八大故障解决办法
- Github Actions实现自定义编译OpenWRT固件和第三方插件
- gentoo linux 内核,手动升级Gentoo及其内核的方法
- Think On Paper
- 博客上怎么根据搜索ID搜索其它人
- 软碟通 (UltraISO)制作启动盘
- 时间类型转换的问题“2021-01-20T10:09:11Z”
热门文章
- iphone屏蔽系统更新_未越狱屏蔽系统更新还是来了
- 112. Leetcode 673. 最长递增子序列的个数 (动态规划-子序列问题)
- 29. Leetcode 19. 删除链表的倒数第 N 个结点 (链表-双指针)
- 13. Leetcode 349. 两个数组的交集 (数组-分离双指针)
- pytorch模型的保存与加载
- TensorFlow 安装protoc
- 背景和文字分离的matlab实现
- java带参数的构造方法_崤云说 | JAVA面向对象
- 35+ Top Apache Tomcat Interview Questions And Answers【转】
- Kafka设计解析(七)- 流式计算的新贵 Kafka Stream