热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【c++】重载操作符

目录输入和输出操作符算术操作符和关系操作符下标操作符自加、自减操作符成员访问操作符1输入和输出操作符1.1输出操作符1.1.1示例#include#inclu

目录

  1. 输入和输出操作符
  2. 算术操作符和关系操作符
  3. 下标操作符
  4. 自加、自减操作符
  5. 成员访问操作符

1  输入和输出操作符

1.1 输出操作符

1.1.1 示例

#include
#include
<string>
using namespace std;class A
{friend ostream
& operator<<(ostream& out, const A& a);public:A(const string &s &#61; "", int v &#61; 0) : ss(s), val(v) {} //构造函数带默认参数private:int val;string ss;
};ostream
& operator<<(ostream& out, const A& a)
{
out <<"a.ss:" <" " <<"a.val:" << a.val;return out;
}
int main()
{A a(
"hello", 23);cout < endl;A b;cout < endl;
}

结果

1.1.2 说明

1&#xff09;IO操作必须为非成员函数

原因&#xff1a;I/O操作的接口返回的是ostream&对象&#xff08;只有返回左值&#xff0c;这样才可以连续的输出&#xff0c;例如cout <

2&#xff09;因为要访问指定类的私有成员&#xff0c;所以在该类中声明输出操作符为友员函数。

3&#xff09;第一个形参必须为引用。因为I/O对象不可以复制。同理返回值必须为一个引用。

4&#xff09;第一个形参不可以为const&#xff0c;因为写入到流会改变其值。

5&#xff09;第二个为引用&#xff0c;这样可以避免复制。参数可以为const&#xff0c;可以接收const对象和非const对象&#xff1b;否则&#xff0c;如果为非const&#xff0c;则只能接收非coust对象。一般为const&#xff0c;毕竟只是输出而已&#xff0c;不改变对象。

 

1.2 输入操作符

1.2.1 示例

结果

1.2.2 说明

1&#xff09;输入与输出操作符的重要区别&#xff1a;输入操作符必须处理错误和文件结束的可能性。

2&#xff09;输入如果有多个值的话&#xff0c;如果一个数错了&#xff0c;整个输入对象就错了&#xff08;False&#xff09;&#xff0c;从示例中可以看出&#xff0c;前边赋值正确的已经生效了&#xff0c;后边的用了默认值&#xff0c;可以这样设计&#xff1a;如果输入错误&#xff0c;将整个对象复位&#xff0c;恢复到最初的状态&#xff0c;例&#xff1a;

 View Code

 

2 算术操作符和关系操作符

2.1 相等操作符

2.1.1 示例

#include
#include
<string>
using namespace std;class A
{friend
bool operator&#61;&#61;(const A& a, const A& b);friend bool operator!&#61;(const A& a, const A& b);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}private:string ss;int val;
};
bool operator&#61;&#61;(const A& a, const A& b)
{
return a.ss &#61;&#61; b.ss && a.val &#61;&#61; b.val;
}
bool operator!&#61;(const A& a, const A& b)
{
return !(a &#61;&#61; b);
}
int main()
{A a(
"hello", 53);A b("hello", 54);A c("hello", 54);cout <<"a &#61;&#61; b?:" <<(a &#61;&#61; b) << endl;cout <<"a !&#61; b?:" <<(a !&#61; b) << endl;cout <<"b &#61;&#61; c?:" <<(b &#61;&#61; c) << endl;cout <<"b !&#61; c?:" <<(b !&#61; c) << endl;
}

结果

2.1.2说明

1&#xff09;定义了类的&#61;&#61;&#xff0c;对应的应该定义&#xff01;&#61;

 

2.2 关系操作符

2.2.1 示例

#include
#include
<string>
using namespace std;class A
{friend
bool operator<(const A& a, const A& b);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}private:string ss;int val;
};
bool operator<(const A& a, const A& b)
{
return (a.val < b.val);
}
int main()
{A a(
"hello", 53);A b("he", 55);cout <<"a " <<(a endl;
}

结果

2.2.2 说明

1&#xff09;定义了相等操作符&#xff0c;一般也定义关系操作符

2&#xff09;关系操作符要根据具体的含义定义

 

2.3 赋值操作符

2.3.1 示例

#include
#include
<string>
using namespace std;class A
{friend ostream
& operator<<(ostream& out, const A& a);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}A& operator&#61;(const A& a);private:string ss;int val;
};ostream
& operator<<(ostream &out, const A& a)
{
out <<"a.ss:" <" " <<"a.val:" << a.val;
}A
& A::operator&#61;(const A& a)
{
if(this !&#61; &a){ss &#61; a.ss;val &#61; a.val;}return *this;
}
int main()
{A a(
"hello", 53);A b("he", 55);cout < endl;b &#61; a;cout < endl;
}

2.3.2 说明

1&#xff09; 复制操作符完成对同类对象的赋值&#xff0c;参数一般为对类类型的const引用。

2&#xff09;如果没有&#xff0c;编译器会自动合成一个&#xff0c;类的赋值操作符一定为类的成员变量&#xff0c;以便编译器是否需要自己合成一个。

3&#xff09;返回值必须为*this的引用&#xff0c;这样就不需要创建和撤销结果的临时副本。同理的有复合赋值操作符&#xff0c;例如

 View Code

结果

 

2.4 加法操作符

2.4.1 示例

2.4.2 说明

1&#xff09; 根据复合操作符&#xff08;如&#43;&#61;&#xff09;实现算术操作符&#xff08;如&#43;&#xff09;&#xff0c;比其他方式更有效

 

3 下标操作符

3.1.1 示例

#include
#include
<string>
using namespace std;class A
{friend ostream
& operator<<(ostream& out, const A& a);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}char& operator[](const size_t);const& char operator[](const size_t) const;private:string ss;int val;
};ostream
& operator<<(ostream& out, const A& a)
{
out <<"a.val:" <" " <<"a.ss:" << a.ss;return out;
}
char& A::operator[](const size_t index)
{
return ss[index];
}
const char& A::operator[](const size_t index) const
{
return ss[index];
}
int main()
{A a(
"hello", 53);cout <2] << endl;
}

结果

e

3.1.2 说明

1&#xff09; 下标操作必须为函数成员&#xff0c;因为传递一个参数&#xff0c;还需要另一个指向自己的指针参数&#xff0c;正好函数成员的this可以胜任。

2&#xff09; 类定义下标时&#xff0c;一般定义两个版本&#xff1a;一个为非const成员&#xff0c;并返回非const引用&#xff1b; 另一个为const成员&#xff0c;并返回const引用。这样应用与const对象时&#xff0c;返回值应为const引用&#xff0c;不能用作赋值的目标。

 

4 自加、自减操作符

4.1 前置自加、自减操作符

4.1.1 示例

结果

 

4.2 后置自加、自减操作符

4.2.1 示例

4.2.2 说明

1&#xff09;为了区分与前置自加、自减操作符的区别&#xff0c;后置需要接受一个而外的&#xff08;无用的&#xff09;的int型形参。使用后缀式操作符时&#xff0c;编译器提供0作为这个形参的实参&#xff0c;其唯一目的是为了区别前缀、后缀。

2&#xff09;a&#43;&#43;返回的是加之前的状态&#xff0c;因此&#xff0c;定义一个局部对象&#xff0c;保存&#xff08;*this&#xff09;&#xff0c;最后返回这个局部变量的备份&#xff08;注意不可以为引用&#xff0c;毕竟是局部的&#xff09;。

 

5. 成员访问操作符

5.1.1 示例

#include
#include
<string>
using namespace std;
class B
{
public:void print_B() { cout <<"hello !!" << endl; }
};
class U_Ptr
{friend
class HasPtr;B* ip;size_t use;U_Ptr(B *p) : ip(p), use(1) {}~U_Ptr() { delete ip; }
};
class HasPtr
{
public:HasPtr(B *p, int i) : ptr(new U_Ptr(p)), val(i) {}HasPtr(const HasPtr &orig) : ptr(orig.ptr), val(orig.val) { &#43;&#43;ptr->use; }HasPtr& operator&#61;(const HasPtr &orig);~HasPtr() { if(--ptr->use &#61;&#61; 0) delete ptr; }B& operator*() { return *ptr->ip; }B* operator->() { return ptr->ip; }private:U_Ptr *ptr;int val;
};HasPtr
& HasPtr::operator&#61;(const HasPtr &orig)
{
if(this !&#61; &orig){ptr &#61; orig.ptr;val &#61; orig.val;&#43;&#43;(ptr->use);}return *this;
}
int main()
{HasPtr hasptr1(
new B, 23);HasPtr hasptr2(hasptr1);*hasptr1;hasptr1->print_B();
}

结果

hello!!

5.1.2 说明

1&#xff09; 箭头必须定义为成员函数&#xff0c; 解引用不要求定义为成员&#xff0c;但是可以作为成员。

2&#xff09; 解引用和箭头操作常用在实现智能指针的类中。

 

 




本文转自jihite博客园博客&#xff0c;原文链接&#xff1a;http://www.cnblogs.com/kaituorensheng/p/3505115.html&#xff0c;如需转载请自行联系原作者



推荐阅读
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
author-avatar
zaizaiwaipo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有