热门标签 | 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;如需转载请自行联系原作者



推荐阅读
  • HDU 2537 键盘输入处理
    题目描述了一个名叫Pirates的男孩想要开发一款键盘输入软件,遇到了大小写字母判断的问题。本文提供了该问题的解决方案及实现方法。 ... [详细]
  • 题面:P3178[HAOI2015]树上操作好像其他人都嫌这道题太容易了懒得讲,好吧那我讲。题解:第一个操作和第二个操作本质上是一样的&# ... [详细]
  • 本文详细探讨了select和epoll两种I/O多路复用技术的内部实现原理,分析了它们在处理大量文件描述符时的性能差异,并通过具体示例代码展示了select的工作流程。 ... [详细]
  • 在学习了Splay树的基本查找功能后,可能会觉得它与普通的二叉查找树没有太大的区别,仅仅是通过splay操作减少了时间开销。然而,Splay树之所以被誉为“序列之王”,主要在于其强大的区间操作能力。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • 使用 ModelAttribute 实现页面数据自动填充
    本文介绍了如何利用 Spring MVC 中的 ModelAttribute 注解,在页面跳转后自动填充表单数据。主要探讨了两种实现方法及其背后的原理。 ... [详细]
  • UVa 11683: 激光雕刻技术解析
    自1958年发明以来,激光技术已在众多领域得到广泛应用,包括电子设备、医疗手术工具、武器等。本文将探讨如何使用激光技术进行材料雕刻,并通过编程解决一个具体的激光雕刻问题。 ... [详细]
  • 题目概述:Sereja 拥有一个由 n 个整数组成的数组 a1, a2, ..., an。他计划执行 m 项操作,这些操作包括更新数组中的特定元素、增加数组中所有元素的值,以及查询数组中的特定元素。 ... [详细]
  • 本文针对HDU 1042 N! 问题提供详细的解析和代码实现。题目要求计算给定整数N(0 ≤ N ≤ 10000)的阶乘N!。文章不仅提供了算法思路,还附上了C++语言的具体实现。 ... [详细]
  • 编程解析:CF989C 花朵之雾 (构造算法)
    本文深入探讨了CF989C '花朵之雾'问题的构造算法,提供了详细的解题思路和代码实现。 ... [详细]
  • 本文基于Java官方文档进行了适当修改,旨在介绍如何实现一个能够同时处理多个客户端请求的服务端程序。在前文中,我们探讨了单客户端访问的服务端实现,而本篇将深入讲解多客户端环境下的服务端设计与实现。 ... [详细]
  • 探讨了一个包含纯虚函数的C++代码片段,分析了其中的语法错误及逻辑问题,并提出了修正方案。 ... [详细]
  • 使用REM和媒体查询实现响应式布局
    本文介绍如何利用REM单位和媒体查询(Media Queries)来创建适应不同屏幕尺寸的网页布局。通过具体示例,展示在不同屏幕宽度下如何调整页面元素的样式。 ... [详细]
  • 本文介绍了一种使用链剖分(Link-Cut Tree, LCT)来维护动态树结构的方法,特别是如何通过 LCT 来高效地管理子树的信息,如子树大小等。 ... [详细]
  • 想把一组chara[4096]的数组拷贝到shortb[6][256]中,尝试过用循环移位的方式,还用中间变量shortc[2048]的方式。得出的结论:1.移位方式效率最低2. ... [详细]
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社区 版权所有