C++之运算符重载(下)

4.提高

1.运算符重载机制
编译器实现运算符重载实际上就是通过函数重载实现的,可分为全局函数方式,也可分为成员函数方式进行重载,并没有改变原操作符的属性和语义。只是针对某个特定类定义一种新的数据类型操作。
2.重载赋值运算符


  • 赋值运算符重载用于对象数据的复制
  • operator= 必须重载为成员函数
  • 重载函数原型为:
    类型 & 类名 :: operator= ( const 类名 & ) ;

结论:
1 先释放旧的内存
2 返回一个引用
3 =操作符 从右向左
#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
using namespace std;//class  Name
{
public:Name(const char *myp){m_len = strlen(myp);m_p =(char *) malloc(m_len + 1); //strcpy(m_p, myp);}//Name obj2 = obj1;//解决方案: 手工的编写拷贝构造函数 使用深copyName(const Name& obj1){m_len = obj1.m_len;m_p = (char *)malloc(m_len + 1);strcpy(m_p, obj1.m_p);}//obj3 = obj1;  // C++编译器提供的 等号操作 也属 浅拷贝//obj3.operator=(obj1)Name& operator=(Name &obj1){//先释放旧的内存if (this->m_p != NULL){delete[] m_p;m_len = 0;}//2 根据obj1分配内存大小this->m_len = obj1.m_len;this->m_p = new char [m_len+1];//把obj1赋值strcpy(m_p, obj1.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; 
};//对象析构的时候 出现coredump
void objplaymain()
{Name obj1("abcdefg");Name obj2 = obj1;  //C++编译器提供的 默认的copy构造函数  浅拷贝Name obj3("obj3");obj3 = obj1;  // C++编译器提供的 等号操作 也属 浅拷贝//obj3.operator=(obj1)//operato=(Name &obj1)obj1 = obj2 = obj3;//obj2.operator=(obj3);//obj1 = void;
}void main()
{objplaymain();cout<<"hello..."<<endl;system("pause");return ;
}

3.重载下标运算符

  • [ ]运算符用于访问数据对象的元素
  • 重载格式 类型 类 :: operator[] ( 类型 ) ;
  • 只能用成员函数重载,不能用友元函数重载

示例:
设 x 是类 X 的一个对象,则表达式
x [ y ]
可被解释为
x . operator [ ] ( y )
这里写图片描述
这里写图片描述

函数返回值当左值需要返回一个引用!

4.带下标和相等操作符的数组类

  • 类的头文件
#ifndef NEWARRAY_H
#define NEWARRAY_H
#include <iostream>
#include <stdlib.h>class NewArray
{
public:NewArray();NewArray(int _len);NewArray(const NewArray & obj);~NewArray();void setData(int index,int var);int getData(int index);int length();int& operator[](int i);NewArray& operator=(NewArray& obj);bool operator==(NewArray& obj);bool operator!=(NewArray& obj);private:int m_len;int *m_buf;
};#endif // NEWARRAY_H
  • 类的实现文件
#include "newarray.h"NewArray::NewArray()
{m_buf = NULL;m_len = -1;
}NewArray::NewArray(int _len)
{if(_len < 0)_len = 0;m_len = _len;m_buf = new int[m_len];}
NewArray::NewArray(const NewArray & obj)
{m_len = obj.m_len;m_buf = new int[m_len];for(int i = 0;i < m_len;i++){m_buf[i] = obj.m_buf[i];}
}
NewArray::~NewArray()
{if(m_buf != NULL){delete []m_buf;m_buf = NULL;m_len = -1;}
}void NewArray::setData(int index,int var)
{m_buf[index] = var;
}
int NewArray::getData(int index)
{return  m_buf[index];
}
int NewArray::length()
{return m_len;
}int& NewArray::operator[](int i)
{return m_buf[i];
}
NewArray& NewArray::operator=(NewArray& obj)
{if(m_buf != NULL){delete []m_buf;m_len = -1;m_buf = NULL;}m_len = obj.m_len;m_buf = new int[m_len];for(int i = 0;i < m_len;i++){m_buf[i] = obj.m_buf[i];}return *this;}
bool NewArray::operator==(NewArray& obj)
{if(m_len != obj.m_len){return false;}for(int i = 0;i < m_len;i++){if(m_buf[i] != obj.m_buf[i]){return false;}}return true;
}
bool NewArray::operator!=(NewArray& obj)
{return !((*this) == obj);
}
  • 测试文件
#include "newarray.h"
using namespace std;int main()
{NewArray  a1(10);for (int i=0; i<a1.length(); i++){//成员函数方式赋值a1.setData(i, i);//下标运算符重载赋值a1[i] = i;//函数返回值当左值,需要返回一个引用//a1.operator [i]}cout<<"\na1: ";for (int i=0; i<a1.length(); i++){//cout<<a1.getData(i)<<" ";//成员函数方式获取元素//下标运算符方式获取数组元素cout<<a1[i]<<"\t";}cout<<endl;//赋值运算符重载NewArray a2 = a1;cout<<"\na2: ";for (int i=0; i<a2.length(); i++){cout<<a2.getData(i)<<" ";}cout<<endl;//3NewArray a3(5);{a3 = a1;a3 = a2 = a1;cout<<"\na3: ";for (int i=0; i<a3.length(); i++){cout<<a3[i]<<" ";}}//功能4if (a3 == a1){printf("\nequal\n");}else{printf("\nnot equal\n");}//a3.operator==(a1);//bool operator==(Array &a1);if (a3 != a1){printf("\nnot equal\n");}else{printf("\nequal\n");}////a3.operator!=(a1)// bool operator!=(Array &a1);cout<<"hello..."<<endl;return 1;
}

5.重载函数调用运算符

  • () 运算符用于函数调用
  • 重载格式
类型 类 :: operator() ( 表达式表 ) ;
  • 只能用成员函数重载,不能用友元函数重载

例1
设 x 是类 X 的一个对象,则表达式
x ( arg1, arg2, … )
可被解释为
x . operator () (arg1, arg2, … )
案例:

  • 例2:用重载()运算符实现数学函数的抽象
#include <iostream>
class  F{ public :  double  operator ( )  ( double x ,  double  y ) ;} ;
double  F :: operator ( )  ( double  x ,  double  y ){ return   x * x + y * y ; }
void main ( )           
{ 
F  f  ;
f.getA();cout << f ( 5.2 , 2.5 ) << endl ;  // f . operator() (5.2, 2.5)
}
  • 例3 用重载()运算符实现 pk 成员函数
#include <iostream.h>
class  F{ public :  double  memFun ( double x ,  double  y ) ;} ;
double  F :: memFun ( double  x ,  double  y ){ return   x * x + y * y ; }
void main ( )           
{ 
F  f  ;cout << f.memFun ( 5.2 , 2.5 ) << endl ;
}

6.不建议重载的运算符

理论知识:
1)&&和||是C++中非常特殊的操作符
2)&&和||内置实现了短路规则
3)操作符重载是靠函数重载来完成的
4)操作数作为函数参数传递
5)C++的函数参数都会被求值,无法实现短路规则

#include <cstdlib>
#include <iostream>using namespace std;class Test
{int i;
public:Test(int i){this->i = i;}Test operator+ (const Test& obj){Test ret(0);cout<<"执行+号重载函数"<<endl;ret.i = i + obj.i;return ret;}bool operator&& (const Test& obj){cout<<"执行&&重载函数"<<endl;return i && obj.i;}
};// && 从左向右
void main()
{int a1 = 0;int a2 = 1;cout<<"注意:&&操作符的结合顺序是从左向右"<<endl;if( a1 && (a1 + a2) ){cout<<"有一个是假,则不在执行下一个表达式的计算"<<endl;}Test t1 = 0;Test t2 = 1;//if( t1 && (t1 + t2)  )//t1  && t1.operator+(t2)// t1.operator&&(  t1.operator+(t2) )   //1 && || 重载他们 不会产生短路效果if(  (t1 + t2) && t1){//t1.operator+(t2) && t1;//(t1.operator+(t2)).operator&&(t1);cout<<"两个函数都被执行了,而且是先执行了+"<<endl;}//2 && 运算符的结合性// 两个逻辑与运算符  在一块的时候, 采去谈 运算符的结合性// 从左到右    (t1 + t2) && t1 ; 运算结果 && t2)//if(  (t1 + t2) && t1 && t2){//t1.operator+(t2) && t1;//(t1.operator+(t2)).operator&&(t1);cout<<"两个函数都被执行了,而且是先执行了+"<<endl;}system("pause");return ;
}

5.字符串类的实现

  • 头文件
#ifndef MYSTRING_H
#define MYSTRING_H
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
class MyString
{
public:MyString();MyString(int _len);MyString(const char *_str);MyString(const MyString & obj);~MyString();MyString& operator =(const MyString & obj);MyString& operator =(const char * _str);bool operator ==(const MyString & obj);bool operator ==(const char * _str);bool operator !=(const MyString & obj);bool operator !=(const char * _str);bool operator >(const MyString & obj);bool operator >(const char * _str);bool operator <(const MyString & obj);bool operator <(const char * _str);char& operator [](int index);friend ostream& operator<<(ostream & out,MyString & obj);friend istream& operator>>(istream & in,MyString & obj);private:int m_len;char *m_str;
};#endif // MYSTRING_H
  • 实现文件
#include "mystring.h"MyString::MyString()
{m_len = 0;m_str = NULL;
}
MyString::MyString(int _len)
{if(_len < 0)_len = 0;m_len = _len;m_str = new char[m_len+1];memset(m_str,0,m_len);
}MyString::MyString(const char *_str)
{if(_str == NULL){m_len = 0;m_str = new char[m_len+1];strcpy(m_str,"");}else{m_len = strlen(_str);m_str = new char[m_len+1];strcpy(m_str,_str);}}
MyString::MyString(const MyString & obj)
{m_len = obj.m_len;m_str = new char[m_len+1];strcpy(m_str,obj.m_str);
}
MyString::~MyString()
{if(m_str != NULL){delete []m_str;m_str = NULL;m_len = 0;}
}MyString& MyString::operator =(const MyString & obj)
{if(m_str != NULL){delete []m_str;m_str = NULL;m_len = 0;}m_len = obj.m_len;m_str = new char[m_len+1];strcpy(m_str,obj.m_str);return *this;
}MyString& MyString::operator =(const char * _str)
{if(m_str != NULL){delete []m_str;m_str = NULL;m_len = 0;}if(_str == NULL){m_len = 0;m_str = new char[m_len+1];strcpy(m_str,"");}else{m_len = strlen(_str);m_str = new char[m_len+1];strcpy(m_str,_str);}return *this;
}bool MyString::operator ==(const MyString & obj)
{if(m_len != obj.m_len){return false;}return !strcmp(m_str,obj.m_str);}bool MyString::operator ==(const char * _str)
{if(_str == NULL){if(m_len == 0){return true;}else{return false;}}else{if(m_len == strlen(_str)){return !strcmp(m_str,_str);}else{return false;}}}bool MyString::operator !=(const MyString & obj)
{return !((*this) == obj);
}bool MyString::operator !=(const char * _str)
{return !((*this) == _str);
}bool MyString::operator >(const MyString & obj)
{if(strcmp(m_str,obj.m_str) > 0){return true;}else{return false;}
}bool MyString::operator >(const char * _str)
{if(strcmp(m_str,_str) > 0){return true;}else{return false;}
}bool MyString::operator <(const MyString & obj)
{if(strcmp(m_str,obj.m_str) < 0){return true;}else{return false;}
}bool MyString::operator <(const char * _str)
{if(strcmp(m_str,_str) < 0){return true;}else{return false;}
}char& MyString::operator [](int index)
{return m_str[index];
}ostream& operator<<(ostream & out,MyString & obj)
{out<<obj.m_str;return out;
}istream& operator>>(istream & in,MyString & obj)
{in>>obj.m_str;return in;
}
  • 测试文件
#define _CRT_SECURE_NO_WARNINGS#include "mystring.h"void main01()
{MyString s1;MyString s2("s2");MyString s2_2 = NULL;MyString s3 = s2;MyString s4 = "s4444444444";//测试运算符重载 和 重载[]//=s4 = s2;s4 = "s2222";s4[1] = '4';printf("%c", s4[1]);cout<<s4 <<endl;//ostream& operator<<(ostream &out, MyString &s)//char& operator[] (int index)//MyString& operator=(const char *p);//MyString& operator=(const MyString &s);cout<<"hello..."<<endl;system("pause");return ;
}void main02()
{MyString s1;MyString s2("s2");MyString s3 = s2;if (s2 == "aa"){printf("相等");}else{printf("不相等");}if (s3 == s2){printf("相等");}else{printf("不相等");}}
void main03()
{MyString s1;MyString s2("s2");MyString s3 = s2;s3 = "aaa";if (s3 < "bbbb" ){printf("s3 小于 bbbb");}else{printf("s3 大于 bbbb");}MyString s4 = "aaaaffff";//strcpy(s4.c_str(), "aa111"); //MFCcout<<s4<<endl;
}void main011()
{MyString s1(128);cout<<"\n请输入字符串(回车结束)";cin>>s1;cout<<s1;system("pause");}int main()
{MyString s1(128);cout<<"\n请输入字符串(回车结束)";cin>>s1;cout<<s1<<endl;system("pause");return 0;}

总结

  • 操作符重载是C++的强大特性之一
  • 操作符重载的本质是通过函数扩展操作符的语义
  • operator关键字是操作符重载的关键
  • friend关键字可以对函数或类开发访问权限
  • 操作符重载遵循函数重载的规则
  • 操作符重载可以直接使用类的成员函数实现
  • =, [], ()和->操作符只能通过成员函数进行重载
  • ++操作符通过一个int参数进行前置与后置的重载
  • C++中不要重载&&和||操作符

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

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

相关文章

Cookie / Session 的机制与安全

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Cookie和Session是为了在无状态的HTTP协议之上维护会话状态&#xff0c;使得服务器可以知道当前是和哪个客户在打交道。本文来详细讨论C…

Servlet快速入门及运行流程

一、Servlet快速入门 1.创建一个web工程 2.在JavaResource中src下创建一个包名称为com.myxq.servlet 3.在创建的servlet包当中创建一个class文件起名为FirstServlet 4.进入该class实现一个Servlet接口&#xff0c;实现它未实现的方法 重点看service方法在该方法当中写入一句话进…

C++之多继承

1.基础知识 1.1 类之间的关系 has-A&#xff0c;uses-A 和 is-A has-A 包含关系&#xff0c;用以描述一个类由多个“部件类”构成。实现has-A关系用类成员表示&#xff0c;即一个类中的数据成员是另一种已经定义的类。 常和构造函数初始化列表一起使用 uses-A 一个类部分地…

聊一聊 cookie

我们看到的 cookie 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我自己创建了一个网站&#xff0c;网址为http://ppsc.sankuai.com。在这个网页中我设置了几个cookie&#xff1a;JS…

const的用法,特别是用在函数后面

原文出处&#xff1a;http://blog.csdn.net/zcf1002797280/article/details/7816977

图解 Linux 安装 JDK1.8 、配置环境变量

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 到官网下载 JDK 1.8 https://www.oracle.com/technetwork/java/javase/downloads/index.html 2. 用 rz 命令把 jdk-8u191-linux-x6…

C++之纯虚函数和抽象类

纯虚函数和抽象类 1.基本概念 2.案例 #include <iostream> using namespace std;////面向抽象类编程(面向一套预先定义好的接口编程)//解耦合 ....模块的划分class Figure //抽象类 { public://阅读一个统一的界面(接口),让子类使用,让子类必须去实现virtual void get…

解决: -bash: $‘\302\240docker‘: command not found

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我只是运行 一条很简单的启动容器的命令&#xff0c;多次执行都报错&#xff0c;报错如题&#xff1a; -bash: $\302\240docker: comma…

【汽车取证篇】GA-T 1998-2022《汽车车载电子数据提取技术规范》(附下载)

【汽车取证篇】GA-T 1998-2022《汽车车载电子数据提取技术规范》&#xff08;附下载&#xff09; GA-T 1998-2022《汽车车载电子数据提取技术规范》标准—【蘇小沐】 总结 公众号回复关键词【汽车取证】自动获取资源合集&#xff0c;如链接失效请留言&#xff0c;便于…

解决: Client does not support authentication protocol requested by server; consider upgrading MySQL

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在服务器上把 mysql 装好后&#xff0c;运行起来。 2. navicat 死活连接不上&#xff0c;在网上查说是要改数据库账号、密码什么的&…

C++之STL理论基础

1.基本概念 STL&#xff08;Standard Template Library&#xff0c;标准模板库)是惠普实验室开发的一系列软件的统称。虽然主要出现在C中&#xff0c;但在被引入C之前该技术就已经存在了很长的一段时间。 STL的从广义上讲分为三部分&#xff1a;algorithm&#xff08;算法&am…

解决maven打包报错:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、报错经历&#xff1a; 今天使用eclipse通过maven install打war包的时候&#xff0c;出现了下图所示的错误 二、问题分析&#xff1a…

STL之Vector

1.简介 vector是将元素置于一个动态数组中加以管理的容器。可以随机存取元素&#xff08;支持索引值直接存取&#xff0c;用[]操作符或at()方法&#xff0c;还支持迭代器方式存取&#xff09;。   vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比…

解决 : Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 执行 maven install 命令报错如题&#xff1a; Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:comp…

Docker 镜像 重命名

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 镜像改名命令格式&#xff1a; # 命令格式&#xff1a;docker tag 镜像id 仓库&#xff1a;标签或&#xff1a;docker tag 旧镜…

Java蓝桥杯02——第二题集锦:生日蜡烛、星期一、方格计数、猴子分香蕉

第二题 生日蜡烛(结果填空) 某君从某年开始每年都举办一次生日party&#xff0c;并且每次都要吹熄与年龄相同根数的蜡烛。 现在算起来&#xff0c;他一共吹熄了236根蜡烛。 请问&#xff0c;他从多少岁开始过生日party的&#xff1f; 请填写他开始过生日party的年龄数。 注意&a…

解决:Error response from daemon: Get https://index.docker.io/v1/search?q=openjdkn=25: dial tcp: looku

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 我只是想查一个 mysql 镜像。执行命令&#xff1a; docker search mysql 。报错如下&#xff1a; Error response from daemon…

安装 Git ( Windows、linux、Mac)

安装 Git 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 是时候动手尝试下 Git 了&#xff0c;不过得先安装好它。有许多种安装方式&#xff0c;主要分为两种&#xff0c;一种是通过编…

STL之函数适配器

1.理论知识 2.常用函数适配器 标准库提供一组函数适配器&#xff0c;用来特殊化或者扩展一元和二元函数对象。常用适配器是&#xff1a; 1绑定器&#xff08;binder&#xff09;: binder通过把二元函数对象的一个实参绑定到一个特殊的值上&#xff0c;将其转换成一元函数对象…

pyqt5 + pyinstaller 制作爬虫小程序

环境:mac python3.7 pyqt5 pyinstaller ps: 主要是熟悉pyqt5, 加入了单选框 输入框 文本框 文件夹选择框及日历下拉框 效果图: pyqt5 主程序文件 # -*- coding: utf-8 -*- # Author: Mehaei # Date: 2019-07-10 13:02:56 # Last Modified by: Mehaei # Last Modified time…