一个例子了解operator+
创始人
2024-05-30 13:02:14
0

先来看一个题目:

#include 
using namespace std;class A {int a;
public:A(int x=0): a(x){}void f(){cout << a;}A operator+(int op) {A T;T.a = a + op;return T;}
};int main()
{A a1, a2(2);cout << a1 + a2;  // A(a1 + a2).f();	 // B(a1 + 3).f();	 // C(3 + a1).f();	 // Dreturn 0;
}

以上 main 函数中 A,B,C,D 四个选项能通过编译?

考验对 C++ 中运算符重载的理解的时候到了!先给出答案:

cout << a1 + a2;	// A  --> failed
(a1 + a2).f();		// B  --> failed
(a1 + 3).f();		// C  --> passed
(3 + a1).f();		// D  --> passed

为啥会是这样呢?看一个稍复杂些的例子(把各种情况都列一下):

#include 
using namespace std;class A {int a;
public:A(int x=0): a(x){}void f(){cout << "operator+(int): " << a << endl;}A operator+(A op) {A T;T.a = a + op.a;return T;}
};class B {int b;
public:B(int x=0): b(x) {}void f() {cout << "operator+(Obj): " << b << endl;}B operator+(int op) {B T;T.b = b + op;return T;}
};int main()
{A a1, a2(2);B b1, b2(2);// operator+ 的参数为 A 时,int 型 op 作为第二操作数(a1 + 3).f(); // pass// operator+ 的参数为 A 时,int 型 op 作为第一操作数(3 + a1).f();  // failed// operator+ 的参数为 A 时,A 型 op 作为操作数(a1 + a2).f();  // pass// operator+ 的参数为 int 时,int 型 op 作为第二操作数(b1 + 3).f();  // pass// operator+ 的参数为 int 时,int 型 op 作为第一操作数(3 + b1).f();  // failed// operator+ 的参数为 int 时,B 型 op 作为操作数(b1 + b2).f(); // failedreturn 0;
}

以上各个例子,可以发现一个规律:加法操作操作符有两个操作数,能否能够编译取决于对象是第几个操作数以及重载 operator+ 时的参数类型,且成员函数默认把 this 指针当作第一个参数传进去了。例如,(a1 + 3).f()pass 是因为定义了 operator+(A),等价于 operator+(A, A),因为 3 可以通过构造函数转化为 A(3) 所以执行时相当于:第一个操作数是 a1,所以调用的是 A 重载的加法运算符,然后用 3 实例化为一个 A 类型的对象,再传给 operator+。所以,能否编译通过,我们要看第一个操作数的类型来确定,再根据第二个操作数来确定参数的类型,如果第一个操作数的类型中定义了该签名的 operator+ 则可以编译通过,否则 failed。所以:

 // operator+ 的参数为 A 时,int 型 op 作为第二操作数(a1 + 3).f(); // pass。目标:operator+(A, int),存在:operator(A*, A),3 可以实例化为 A,所以 passed// operator+ 的参数为 A 时,int 型 op 作为第一操作数(3 + a1).f();  // failed。目标:operator+(int, A),存在:operator(A*, A),不匹配,如果 A 中引入友元函数 operator(int, A) 则可以 passed// operator+ 的参数为 A 时,A 型 op 作为操作数(a1 + a2).f();  // pass。显然!// operator+ 的参数为 int 时,int 型 op 作为第二操作数(b1 + 3).f();  // pass。目标:operator+(B, int),存在:operator+(B*, int)// operator+ 的参数为 int 时,int 型 op 作为第一操作数(3 + b1).f();  // failed。目标:operator+(int, B),存在:operator+(B*, int),不匹配,如果 B 中引入友元函数 operator+(int, B) 则 passed// operator+ 的参数为 int 时,B 型 op 作为操作数(b1 + b2).f(); // failed。目标:operator+(B, B),存在:operator+(B*, int),不匹配

引入友元函数的例子:

class A {int a;
public:A(int x=0): a(x){}void f(){cout << "operator+(int): " << a << endl;}A operator+(A op) {  // 其实等价于:operator+(A* , A),this 指针作为第一个参数A T;T.a = a + op.a;return T;}friend A operator+(int op1, A op2) {  // 友元函数A T;T.a = op1 + op2.a;return T;}
};

这种情况下 (3 + a1).f() 即可 passed

结论:根据操作数的类型和位置确定需要的 operator+ 的具体函数签名,如果在名字空间中能找到定义的函数则可以,否则 failed!

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...