C++基础11-类和对象之操作符重载1

总结:

1、运算符重载的本质是函数重载
2、运算符重载可分为成员函数重载全局函数重载(差一个参数)
3、运算符重载函数的参数至少有一个是类对象(或类对象的引用)
4、不可以被重载的操作符有:成员选择符(.) 成员对象选择符(.*) 
                                                 域解析操作符(::) 条件操作符(?:)
5、前置加加 可以连续使用 后置加加 不可以连续使用
6、前置加加(减减)的运算符重载和普通运算符重载一样后置加加(减减)的运算符重载需要加一个占位符
7、输入输出运算符重载定义为全局函数重载。因为成员函数重载会发生歧义
8、输入输出运算符重载借助输入输出流(ostream istream)
9、双目运算符就是有两个参数(+,-),单目运算符有一个参数(++,--)
10、重载的前置加加 Complex& operator++(Complex &c1)  //返回引用的目的是使用连续前置加加
       重载的后置加加 const Complex& operator++(Complex &c1, int) 
                                  //加const的原因是后置加加不能连续使用
11、右移操作符重载:friend ostream& operator<<(ostream &os, Complex &c);
                    ostream& operator<<(ostream &os)  //c1.operator<<(cout)
                    { 
                        os << "(" << this->a << "," << this->b << "i)";
                        return os;
                    }
     左移操作符重载:friend istream& operator>>(istream &is, Complex &c);
                    istream& operator>>(istream &is, Complex &c)
                    {
                        cout << "a:";
                        is >> c.a;
                        cout << "b:";
                        is >> c.b;
                        return is;
                    }
12、若某函数中类想引用私有成员,则将此函数在这个类中声明为友元函数

13、除了赋值号(=)外,基类中被重载的操作符都将被派生类继承

1、操作符重载格式

重载函数的一般格式如下:

函数类型 operator 运算符名称(形参表列) {

         重载实体;

}

operator 运算符名称 在一起构成了新的函数名。比如

const Complex operator+(const Complex &c1,const Complex &c2);

我们会说,operator+ 重载了重载了运算符+。

2、重载规则

 

4.10.2 重载规则

(1)C++不允许用户自己定义新的运算符,只能对已有的 C++运算符进行重载。

例如,有人觉得 BASIC 中用“* *”作为幂运算符很方便,也想在 C++中将“**”定义为幂运算符,用“3**5”表示 35,这是不行的。

(2)C++允许重载的运算符

C++中绝大部分运算符都是可以被重载的。

不能重载的运算符只有 4 个:成员选择符(.) 成员对象选择符(.*)   域解析操作符(::) 条件操作符(?:)

前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符合sizeof 运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。

 

3)重载不能改变运算符运算对象(即操作数)的个数。

如,关系运算符“>”和“<”等是双目运算符,重载后仍为双目运算符,需要两 个参数。运算符”+“,”-“,”*“,”&“等既可以作为单目运算符,也可以作为双 目运算符,可以分别将它们重载为单目运算符或双目运算符。

4)重载不能改变运算符的优先级别。

例如”*“和”/“优先级高于”+“和”-“,不论怎样进行重载,各运算符之间的优先级不会改变。有时在程序中希望改变某运算符的优先级,也只能使用加括号的方法 强制改变重载运算符的运算顺序。

(5)重载不能改变运算符的结合性。

如,复制运算符”=“是右结合性(自右至左),重载后仍为右结合性。

(6)重载运算符的函数不能有默认的参数

否则就改变了运算符参数的个数,与前面第(3)点矛盾。

(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有 一 个是类对象(或类对象的引用)。

也就是说,参数不能全部是 C++的标准类型,以防止用户修改用于标准类型数据成 员的运算符的性质,

(8)用于类对象的运算符一般必须重载,但有两个例外,运算符”=“和运算 符”&“不 必用户重载。

复制运算符”=“可以用于每一个类对象,可以用它在同类对象之间相互赋值。因为系统已为每一个新声明的类重载了一个赋值运算符,它的作用是逐个复制类中的 数据成员地址运算符&也不必重载,它能返回类对象在内存中的起始地址。

(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能。

例如,我们会去重载”+“以实现对象的相加,而不会去重载”+“以实现对象相 减的功能,因为这样不符合我们对”+“原来的认知。

(10)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数

操作符重载

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}friend Complex complexAdd(Complex &c1, Complex &c2);/*friend Complex operator+(Complex &c1, Complex &c2);friend Complex operator-(Complex &c1, Complex &c2);*/Complex complexAdd(Complex &another){Complex temp(this->a + another.a, this->b + another.b);return temp;}//2操作符重载写在局部Complex operator+(Complex &another){Complex temp(this->a + another.a, this->b + another.b);return temp;}Complex operator-(Complex &another){Complex temp(this->a - another.a, this->b - another.b);return temp;}private:int a;//实数int b;//虚数
};Complex complexAdd(Complex &c1, Complex &c2) 
{Complex temp(c1.a + c2.a, c1.b + c2.b);   //要访问需要声明为友元函数return temp;
}
void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();Complex c3 = complexAdd(c1, c2);c3.printComplex();
}void test02() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();Complex c3 = c1.complexAdd(c2);c3.printComplex();
}
//1操作符重载写在全局
#if 0
Complex operator+(Complex &c1, Complex &c2)  //+ 相当于函数名,接收两个参数//+ 左边是 第一个参数//+ 右边是 第二个参数  顺序固定
{Complex temp(c1.a + c2.a, c1.b + c2.b);return temp;
}Complex operator-(Complex &c1, Complex &c2)
{Complex temp(c1.a - c2.a, c1.b - c2.b);return temp;
}#endif
//全部操作符重载调用
void test03() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();//Complex c3 = operator+(c1, c2);  //ok//等价于Complex c3 = c1 + c2;   //此种为隐式写法// c1 + c2  等价于    operator+(c1,c2)  全局的调用方式// c1 + c2  也等价于  c1.operator+(c2)  局部调用方式//所以局部调用方式和全局调用方式只能存在一个c3.printComplex();
}
void test04() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();//Complex c3=c1.operator+(c2);//等价于Complex c3 = c1 + c2;c3.printComplex();Complex c4 = c1 - c2;c4.printComplex();Complex c5 = c1-c2-c1; //当 operator-函数 返回为元素时ok  //c1-c2返回为匿名对象 //再调用函数 还为匿名对象 拷贝构造给c5//当 operator-函数返回引用时 错误  //c1-c2返回为为temp的别名//再调用函数时 temp已经析构 c1-c2变为乱码 再调用函数仍然为乱码c5.printComplex();
}
int main(void)
{cout << "------test01-----------" << endl;test01();cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();return 0;
}
#endif

双目运算符(有两个参数):

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:/*friend Complex& operator+=(Complex &c1, Complex &c2);friend Complex& operator-=(Complex &c1, Complex &c2);*/Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}//2操作符重载写在局部Complex& operator+=(Complex &another){this->a += another.a;this->b += another.b;return *this;}Complex& operator-=(Complex &another){this->a -= another.a;this->b -= another.b;return *this;}private:int a;//实数int b;//虚数
};//1操作符重载写在全局
#if 0
Complex& operator+=(Complex &c1, Complex &c2)  //+ 相当于函数名,接收两个参数//+ 左边是 第一个参数//+ 右边是 第二个参数  顺序固定
{c1.a += c2.a;c1.b += c2.b;return c1;
}Complex& operator-=(Complex &c1, Complex &c2)
{c1.a -= c2.a;c1.b -= c2.b;return c1;
}#endif
void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();(c1 += c2)+=c2;  //(c1.operator+=(c2)).operator(c2)c1.printComplex();c2.printComplex();
}
/*
( 1, 2i )
( 2, 4i )
( 5, 10i )
( 2, 4i )
*/
//全部操作符重载调用int main(void)
{cout << "------test01-----------" << endl;test01();/*cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0;
}
#endif

单目运算符:

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:/*friend Complex& operator++(Complex &c1);friend Complex& operator--(Complex &c12);friend const Complex& operator++(Complex &c1, int);*/Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}//2操作符重载写在局部Complex& operator++(){this->a ++;this->b ++;return *this;}Complex& operator--(){this->a --;this->b --;return *this;}const Complex& operator++(int) {  //亚元Complex temp(this->a, this->b);this->a++;this->b++;return *this;}private:int a;//实数int b;//虚数
};//1操作符重载写在全局
#if 0
//重载的前置加加
Complex& operator++(Complex &c1)  //+ 相当于函数名,接收两个参数//+ 左边是 第一个参数//+ 右边是 第二个参数  顺序固定
{c1.a ++;c1.b ++;return c1;
}Complex& operator--(Complex &c1)
{c1.a--;c1.b--;return c1;
}#endif
//重载的后置加加  不可以用多次 所以用const限制
#if 0
const Complex& operator++(Complex &c1, int) { Complex temp(c1.a, c1.b);c1.a++;c1.b++;return c1;
}
#endif
void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();++c1;c1.printComplex();/*++c1;c1.printComplex();*/}
/*
( 1, 2i )
( 2, 4i )
( 2, 3i )
( 3, 4i )
*/
void test02() {int a = 0;//a++++;  编译错误 后置加加不可多次Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();c1++;  //后置加加返回值添加const 使得c1++++ 编译错误c1.printComplex();
}
/*
( 1, 2i )
( 2, 4i )
( 2, 3i )
*/
int main(void)
{cout << "------test01-----------" << endl;test01();cout << "------test02-----------" << endl;test02();/*cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0;
}
#endif

左移右移操作符:

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:friend ostream& operator<<(ostream &os, Complex &c);friend istream& operator>>(istream &is, Complex &c);Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}
#if 0//左移操作符只能不能够写在成员函数里 只能写在全局函数中 否则调用顺序会变反 c1<<cout;ostream& operator<<(ostream &os) {  //c1.operator<<(cout)os << "(" << this->a << "," << this->b << "i)";return os;}
#endif//2操作符重载写在局部private:int a;//实数int b;//虚数
};//1操作符重载写在全局
#if 1
//重载的前置加加
ostream& operator<<(ostream &os, Complex &c) {os << "(" << c.a << "," << c.b << "i)";return os;
}
istream& operator>>(istream &is, Complex &c) {cout << "a:";is >> c.a;cout << "b:";is >> c.b;return is;
}
#endifvoid test01() {Complex c1(1, 2);Complex c2(2, 4);cout << c1 << endl;cin >> c2;c1.printComplex();c2.printComplex();//cout << c1; //operator<<(cout,c1) 全局ok 局部不ok//c1 << cout;  ok}
/**/int main(void)
{cout << "------test01-----------" << endl;test01();/*cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0;
}
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux下搜狗安装目录,Linux安装搜狗输入法

本系统使用Ubuntu16.04LTS安装中文输入法Ubuntu17.04中支持IBUS&#xff0c;fcitx等输入法框架。分别介绍两种框架下的中文输入法安装&#xff1a;1.IBUS框架下的拼音输入法1.1在Ubuntu Software搜索“pinyin”&#xff0c;安装列表中第一个&#xff1b;1.2在系统设置-Language…

在Linux系统下实现进程,Linux进程学习(一)之Linux进程的基本知识和实现

最近一周学习了Linux 进程编程的知识&#xff0c;现对其总结如下。在第一部分中我们先对进程的基本概念以及在Linux 中是如何来现实进程的进行介绍Tiger-John说明 &#xff1a;许多人在学习中只注重如何编程&#xff0c;却忘了注重原理,不去深究其基本原理。其实操作系统的原理…

C++基础11-类和对象之操作符重载2

总结&#xff1a; 1、等号操作符重载和拷贝构造函数重载一般用在数据成员中需要单独在堆区开辟内存时(指针) 2、new&#xff0c;delete重载内部还是使用malloc和free 3、逗号表达式(,)、或者(||)&#xff0c;且(&&)&#xff0c;条件表达式(?:)具有短路功能。 但…

linux照片备份软件,Linux、Unix上5个惊艳开源备份软件

Linux和类Unix系统上5个惊艳的开源备份软件&#xff1a;Bacula、Amanda、Backupninja、Backuppc和UrBackup&#xff0c;这些都是既可以使用在Linux上也可以使用在Unix上面&#xff0c;他们的优点就是性能稳定&#xff0c;使用灵活。一个好的备份计划是非常必要的&#xff0c;这…

C/C++混淆点-运算符短路

主要内容如下&#xff1a; 按照C/C标准 1.9.18 节的说明&#xff0c;||,&&,?:三目运算符和逗号运算符采用短路运算&#xff0c;第一个表达式之后作为一个运算顺序点。 1 a && b; 2 a || b; 3 a ? b : c; 4 a, b; 短路运算仅对内置的行为有效&#xff0c;如…

C++基础12-类和对象之操作符重载-string练习

总结&#xff1a; 1、等号操作符重载注意事项&#xff1a; &#xff08;1&#xff09;防止自身赋值 &#xff08;2&#xff09;先将自身的额外开辟的空间回收掉 &#xff08;3&#xff09;执行深拷贝 2、注意函数的返回引用或者元素&#xff1a;如果需要连续使用 …

linux中类似findfirst的函数,findfirst函数的用法

函数名称: findfirst函数原型: int findfirst(char *fname,struct ffblk *ptr,int attrib)函数功能: 寻找与fname相匹配的第一个文件名称函数返回:参数说明: ptr-保存查找到的文件信息所属文件: #include #include int main(){struct ffblk ffblk;int d…

C/C++混淆点-逗号运算符

在C中&#xff0c;逗号是很常用的。作为一个运算符它虽然不常用&#xff0c;但我们也应该学会它的用法。 1.如&#xff1a;a3*4,4*5,5*6; 由于“”的优先级高于“&#xff0c;”&#xff0c;所以程序从左向右运行&#xff0c;即先运行a3*4。之后的4*5&#xff0c;5*6仅仅运行&a…

linux 添加重定向域名,Linux系统中Nginx的安装并进行域名认证和重定向

Linux系统中Nginx的安装并进行域名认证和重定向本文主要介绍Linux系统中Nginx的安装并进行域名认证和重定向&#xff0c;希望通过本知识点的讲解对大家今后的学习和工作有所帮助&#xff0c;下面进行具体介绍&#xff1a;12.6 Nginx安装cd /usr/local/srcwget http://nginx.org…

C/C++混淆点-转义字符

从表中可以看出&#xff0c;在C语言中有三种转义字符&#xff0c;它们是&#xff1a;一般转义字符、八进制转义字符和十六进制转义字符。 所有的转义字符只代表一个字符 1. 一般转义字符 这种转义字符&#xff0c;虽然在形式上由两个字符组成&#xff0c;但只代表一个字符。…

linux如何安装python环境变量中,Windows和linux环境下python安装及环境变量的配置

安装包的安装无需双版本存在情况下安装1)下载源码包2)解压源码包并进入文件夹./configure ; make && make install3)使用python -V查看是否安装成功&#xff0c;安装成功会显示python版本信息需要双版本安装python版本1)同上&#xff0c;需要下载3.6源码包2)解压源码包…

C/C++混淆点-strcat和strcpy区别

一、原因分析 假设&#xff1a; char * strNULL; strnew char[11];你想为字符串str开辟一个存储十个字符的内存空间&#xff0c;然后你现在有两个字符串&#xff1a;char * c1"abc"和char * c2"123";你想将这两个字符串都拼接在str字符串中&#xff0c;你…

linux有读EC RAM的工具吗,Step to UEFI (179)Shell下 EC Ram 读取工具

最近工作需要在 UEFI Shell 下Check EC Ram 的设定&#xff0c;发现手上只有 Windows 下的读取工具(RW Everything)。于是研究了一下如何在Shell 读取 EC Ram。根据【参考1】读取的流程如下&#xff1a;Port 66 CommandsThere are also some EC commands that use ports 0x66 …

C++基础13-类和对象之继承1

在 C中可重用性(software reusability)是通过继承(inheritance)这一机制来实现的。 如果没有掌握继承性,就没有掌握类与对象的精华。 总结&#xff1a; 1、只要是父类中的private成员&#xff0c;不管是什么继承方式&#xff0c;儿子都访问不了&#xff0c;但它是存在在儿子之…

线程锁定CPU linux,linux 线程与CPU绑定

看到很多程序都是根据CPU个数来创建线程个数&#xff0c;当时很不理解他们之间的关系&#xff0c;请教了项目组的同事后才有了大致了解。1. 相关系统函数下面的函数可以通过man命令查询到。SYNOPSIS#define _GNU_SOURCE#include int pthread_setaffinity_np(pthread_t thread, …

C++基础13-类和对象之继承2

总结&#xff1a; 1、子类对象可以当做父类对象使用 2、子类对象可以直接赋值给父类对象 3、子类对象能够直接初始化父类对象 4、父类指针可以直接指向子类对象 5、凡是继承过来的属性和函数都可以在子类中用this-> 进行访问 6、默认构造函数并不会初始化数据成员 7、如果…

linux内核 块驱动程序,linux – 为什么内核使用默认的块驱动程序而不是我的驱动程序代码?...

我写了一个块驱动程序,它创建了一个虚拟块设备(sbd0).我为该块设备注册了所有设备操作:(请参阅2.6.32内核源代码中的include /linux / blkdev.h)static struct block_device_operations sbd_ops {.owner THIS_MODULE,.open sbd_open,.release sbd_close,.ioctl sbd_ioctl,…

C++基础14-类和对象之多继承与虚继承

多继承&#xff1a;一个类有多个直接基类的继承关系称为多继承 总结&#xff1a; 1、一般将具有菱形样式继承方式的某些类声明为虚继承 3、虚继承的主要目的是为了防止二义性 2、虚继承就是在继承方式前加virtual 如果一个派生类从多个基类派生&#xff0c;而这些基类又有一…

linux系统安装ntp,CentOS下NTP安装配置

安装yum install ntp配置文件 /etc/ntp.confrestrict default kod nomodifynotrap nopeer noqueryrestrict -6 default kod nomodify notrap nopeer noqueryrestrict 127.0.0.1restrict -6 ::1# 用restrict控管权限# nomodify - 用户端不能更改ntp服务器的时间参数# noquery - …

C++基础15-类和对象之多态

总结&#xff1a; 1、在父类中申明虚函数时&#xff0c;一般情况下在子类中也申明&#xff08;便于读代码&#xff09; 一、赋值兼容 赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。 赋值兼容是一种默认行为,不需要任何的显示的转化步骤。 …