【C++学习笔记四】运算符重载

当调用一个重载函数和重载运算符时,编译器通过把您所使用的参数类型和定义中的参数类型相比较,巨鼎选用最合适的定义。(重载决策)

重载运算符时带有特殊名称的函数,函数名是由关键字operator和其后要重载的运算符符号构成,与其他函数一样,重载运算符有一个返回类型和一个参数列表。

返回类型 operator 运算符(参数列表)
{...
}

大多数的重载运算符可被定义为不同的非成员函数,或者定义为类成员函数。

不可重载的运算符:

  • .成员访问运算符
  • .* ->*成员指针访问运算符
  • ::域运算符
  • ?:条件运算符
  • #预处理符号
输入输出运算符重载

首先我们需要对流输入输出的原理有一个简单的理解。
cinistream类的对象,coutostream类的对象
cin>>x; 相当于cin.operator>>x;然后会在输入缓冲区中读入整型数据后返回流输入对象cin,方便以后再次输入。

我们可以传统的写法进行运算符重载:

例如:

#include <iostream>
using namespace std;class Distance
{
private:int feet;             // 0 到无穷int inches;           // 0 到 12
public:// 所需的构造函数Distance() {feet = 0;inches = 0;}Distance(int f, int i) {feet = f;inches = i;}ostream& operator<<(ostream& os){os << "英寸:" << feet << "\n英尺:" << inches;return os;}
};
int main()
{Distance d1(20, 18);d1 << cout << endl<< "成功"<< endl;//相当于d1.operator<<(cout)
}

运行结果:

在这里插入图片描述
这样写虽然可以但是不太符合我们的习惯,我们更习惯将cout放到最左边。为了能够适用这种写法,我们需要使用友元函数。

详见代码:

#include <iostream>
using namespace std;class Distance
{
private:int feet;             // 0 到无穷int inches;           // 0 到 12
public:// 所需的构造函数Distance() {feet = 0;inches = 0;}Distance(int f, int i) {feet = f;inches = i;}friend ostream& operator<<(ostream& os,const Distance& x){os << "英寸:" << x.feet << "\n英尺:" << x.inches;return os;}
};
int main()
{Distance d1(20, 18);cout<< d1 << endl<< "成功"<< endl;//相当于d1.operator<<(cout)
}

这样写起来就显得很自然。这里我们通过友元函数进行重载。因为<<是二元操作符的缘故我们需要两个参数。其他操作符也可以使用友元函数进行重载,只需要将操作对象放到参数列表中即可。

自增自减运算符的重载

因为自增自减运算符有前缀和后缀之分,因此在重载时也有所不同。除去实现上的不同,后缀运算符在重载的时候参数列表需要有一个int,来向编译器说明这是一个后缀形式 。例如:

返回类型 operator++ (int)
{}

自增和自减运算符一般是改变对象的状态,所以一般是重载为成员函数。

在实际实现的时候,对于前缀运算符我们直接改变成员的状态然后返回一个相同的成员。对于后缀运算符我们先创建一个对象保存对象的值,然后进行改变,最后返回原来的值。

例如:


#include <iostream>
using namespace std;class Time
{private:int hours;             // 0 到 23int minutes;           // 0 到 59public:// 所需的构造函数Time(){hours = 0;minutes = 0;}Time(int h, int m){hours = h;minutes = m;}// 显示时间的方法void displayTime(){cout << "H: " << hours << " M:" << minutes <<endl;}// 重载前缀递增运算符( ++ )Time operator++ ()  {++minutes;          // 对象加 1if(minutes >= 60)  {++hours;minutes -= 60;}return Time(hours, minutes);}// 重载后缀递增运算符( ++ )Time operator++( int )         {// 保存原始值Time T(hours, minutes);// 对象加 1++minutes;                    if(minutes >= 60){++hours;minutes -= 60;}// 返回旧的原始值return T; }
};
int main()
{Time T1(11, 59), T2(10,40);++T1;                    // T1 加 1T1.displayTime();        // 显示 T1++T1;                    // T1 再加 1T1.displayTime();        // 显示 T1T2++;                    // T2 加 1T2.displayTime();        // 显示 T2T2++;                    // T2 再加 1T2.displayTime();        // 显示 T2return 0;
}
赋值运算符重载

详见实例:

#include <iostream>
using namespace std;class Distance
{private:int feet;             // 0 到无穷int inches;           // 0 到 12public:// 所需的构造函数Distance(){feet = 0;inches = 0;}Distance(int f, int i){feet = f;inches = i;}void operator=(const Distance &D ){ feet = D.feet;inches = D.inches;}// 显示距离的方法void displayDistance(){cout << "F: " << feet <<  " I:" <<  inches << endl;}};
int main()
{Distance D1(11, 10), D2(5, 11);cout << "First Distance : "; D1.displayDistance();cout << "Second Distance :"; D2.displayDistance();// 使用赋值运算符D1 = D2;cout << "First Distance :"; D1.displayDistance();return 0;
}
函数调用运算符()重载

重载函数的参数列表就是()应该加上的内容

#include <iostream>
using namespace std;class Distance
{private:int feet;             // 0 到无穷int inches;           // 0 到 12public:// 所需的构造函数Distance(){feet = 0;inches = 0;}Distance(int f, int i){feet = f;inches = i;}// 重载函数调用运算符Distance operator()(int a, int b, int c){Distance D;// 进行随机计算D.feet = a + c + 10;D.inches = b + c + 100 ;return D;}// 显示距离的方法void displayDistance(){cout << "F: " << feet <<  " I:" <<  inches << endl;}};
int main()
{Distance D1(11, 10), D2;cout << "First Distance : "; D1.displayDistance();D2 = D1(10, 10, 10); // invoke operator()cout << "Second Distance :"; D2.displayDistance();return 0;
}
下标运算符[]重载

同样的,重载函数的参数列表应该和[]中的内容相同。

类成员访问运算符->重载

成员访问运算符可以被重载,只是比较麻烦。它被定义为为一个类赋予指针行为。

  • ->必须是一个成员函数
  • 返回类型必须是指针或者类的对象

类成员访问运算符->通常与指针引用运算符*结合使用。用于实现“智能指针”的功能。这些指针可以自动执行一些操作,如在删除指针的时候同时析构对象等来防止一些内存泄漏的问题。

想要了解更多可以参见:传送门

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

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

相关文章

【C++11新特性】 C++11智能指针之unique_ptr

原创作品&#xff0c;转载请标明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50759210 在前面一篇文章中&#xff0c;我们了解了C11中引入的智能指针之一shared_ptr&#xff0c;今天&#xff0c;我们来介绍一下另一种智能指针unique_ptr。 unique_ptr介绍 uni…

C++派生类对象和基类对象赋值

在C中&#xff0c;我们允许 将派生类对象赋给基类对象。&#xff08;不允许将基类对象赋给派生类对象&#xff09; 只会将基类对象成员赋值用基类指针指向派生类对象。&#xff08;不允许用派生类指针指向基类对象&#xff09; 基类指针只能操作基类中的成员基类引用作为派生类…

【C++11新特性】 C++11智能指针之shared_ptr

http://blog.csdn.net/Xiejingfa/article/details/50750037 原创作品&#xff0c;转载请标明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50750037 C中的智能指针首先出现在“准”标准库boost中。随着使用的人越来越多&#xff0c;为了让开发人员更方便、更安…

C++(纯)虚函数重写时访问权限更改问题

我们知道在Java中是自动实现多态的&#xff0c;Java中规定重写的方法的访问权限不能缩小。那么在C中我们实现多态的时候是否可以更改&#xff08;缩小&#xff09;访问权限呢&#xff1f; 经过测试&#xff0c;得到的答案如下&#xff1a;如果用基类指针指向派生类对象实现多态…

C++ — 智能指针的简单实现以及循环引用问题

http://blog.csdn.net/dawn_sf/article/details/70168930 智能指针 ____________________________________________________ 今天我们来看一个高大上的东西&#xff0c;它叫智能指针。 哇这个名字听起来都智能的不得了&#xff0c;其实等你了解它你一定会有一点失望的。。。。因…

C++(静态)(常量)数据进行初始化问题以及静态变量析构

在C11标准以前我们都不可以在类中对数据成员初始化&#xff0c;仅能在构造函数中进行初始化&#xff1a; class A {int a,b; double c; string d;A():a(1),b(2),c(3),d(""){} };在C11标准以后我们可以在类中对非静态成员进行初始化。实际上的机制是在调用构造函数的…

C++this指针的用法

参考博客&#xff1a;https://www.cnblogs.com/zhengfa-af/p/8082959.html 在 访问对象的非静态成员时会隐式传递一个参数&#xff0c;即对象本身的指针&#xff0c;这个指针名为this。 例如&#xff1a; class A {int a1;public:A(){}void GetA(int a){cout<<this-&g…

C++开发者都应该使用的10个C++11特性

http://blog.jobbole.com/44015/ 感谢冯上&#xff08;治不好你我就不是兽医 &#xff09;的热心翻译。如果其他朋友也有不错的原创或译文&#xff0c;可以尝试推荐给伯乐在线。】 在C11新标准中&#xff0c;语言本身和标准库都增加了很多新内容&#xff0c;本文只涉及了一些皮…

C++不能被声明为虚函数

虚函数是为了实现多态&#xff0c;但是显然并不是所有函数都可以声明为虚函数的。 不能被声明为虚函数的函数有两类&#xff1a; 不能被继承的函数不能被重写的函数 因此&#xff0c;这些函数都不能被声明为虚函数 普通函数构造函数 如果构造函数定义为虚函数&#xff0c;则…

类的声明与定义

类的前向声明&#xff1a; class A;在声明之后&#xff0c;定义之前&#xff0c;类A是一个不完全类型&#xff0c;即知道A是一个类&#xff0c;但是不知道包含哪些成员。不完全类型只能以有限方式使用&#xff0c;不能定义该类型的对象&#xff0c;不完全类型只能用于定义指向…

shared_ptr的一些尴尬

http://blog.csdn.net/henan_lujun/article/details/8984543 shared_ptr在boost库中已经有多年了&#xff0c;C11又为其正名&#xff0c;把他引入了STL库&#xff0c;放到了std的下面&#xff0c;可见其颇有用武之地&#xff1b;但是shared_ptr是万能的吗&#xff1f;有没有什…

C++转换构造函数和类型转换函数

参考博客&#xff1a;https://blog.csdn.net/feiyanaffection/article/details/79183340 隐式类型转换 如果不同类型的数据在一起操作的时候编译器会自动进行一个数据类型转换。例如常用的基本数据类型有如下类型转换关系&#xff1a; 转换构造函数 构造函数有且仅有一个参数…

C++总结8——shared_ptr和weak_ptr智能指针

http://blog.csdn.net/wendy_keeping/article/details/75268687 智能指针的提出&#xff1a;智能指针是存储指向动态分配对象指针的类&#xff0c;用于生存期控制。能够确保正确销毁动态分配的内存&#xff0c;防止内存泄露。 1.智能指针的分类&#xff1a; 不带引用计数的智能…

C++析构函数执行顺序

今天发现主程序中有多个对象时析构函数的执行顺序不是对象定义的顺序&#xff0c;而是对象定义顺序反过来。 思考了一下&#xff0c;结合之前继承、成员对象等的析构函数执行的顺序&#xff0c;我觉得析构函数执行的顺序为&#xff1a;构造函数的顺序反过来&#xff0c;可能是…

c++写时拷贝1

http://blog.csdn.net/SuLiJuan66/article/details/48882303 Copy On Write Copy On Write(写时复制)使用了“引用计数”&#xff08;reference counting&#xff09;&#xff0c;会有一个变量用于保存引用的数量。当第一个类构造时&#xff0c;string的构造函数会根据传入的参…

【C++学习笔记五】模板

模板是泛型编程的基础 函数模板 模板定义以关键字template开始&#xff0c;后跟一个模板参数列表。这是一个逗号分隔的一个或多个模板参数的列表。用尖括号包围起来。 模板函数定义的一般形式&#xff1a; template <class type> ret-tye func-name(parameter list) …

【Java学习笔记十】输入输出流

在Java.io包中提供了一系列用于处理输入/输出的流类。从功能上分为两类&#xff1a;输入流和输出流。从六结构上可分为&#xff1a;字节流&#xff08;以字节为处理单位&#xff09;和字符流&#xff08;以字符为处理单位&#xff09;。 字符是由字节组成。在Java中所有字符用…

C++ 写时拷贝 2

什么情况下会用到c中的拷贝构造函数】&#xff1a; 1&#xff09;用已经存在的同类的对象去构造出另一个新的对象 2&#xff09;当函数的形参是类的对象时&#xff0c;这时调用此函数&#xff0c;使用的是值的拷贝&#xff0c;也会调用拷贝构造函数 3&#xff09;当函数的返…

【Java学习笔记十一】图形用户界面

图形用户界面或图形用户接口(Graphical User Interface&#xff0c;GUI)是指采用图形方式,借助菜单、按钮等标准界面元素&#xff0c;用户可以通过鼠标等外设向计算机系统发出指令、启动操作&#xff0c;并将系统运行的结果同样以图形方式显示给用户的技术。 GUI是事件驱动的&…

C++ 写时拷贝 3

http://blog.csdn.net/ljianhui/article/details/22895505 字符串一种在程序中经常要使用到的数据结构&#xff0c;然而在C中却没有字符串这种类型。在C中&#xff0c;为了方便字符串的使用&#xff0c;在STL中提供了一个string类。该类维护一个char指针&#xff0c;并封装和提…