C++;运算符重载 为什么C++程序下面输出“ACCA”?为什么调用了两次操作符int() #include "stdafx.h" #include <iostream> using namespace std; class Base { public: Base(int m_var=1):i(m_var){ cout<<"A"; } Base(Base& Base){ cout<<"B"; i=Base.i; } operator int() { cout<<"C"; return i; } private: int i; }; int main() { Base obj; obj = obj+obj; return 0; } #包括“stdafx.h” #包括 使用名称空间std; 阶级基础{ 公众: 基数(int m_var=1):i(m_var){ cout
C++;运算符重载 为什么C++程序下面输出“ACCA”?为什么调用了两次操作符int() #include "stdafx.h" #include <iostream> using namespace std; class Base { public: Base(int m_var=1):i(m_var){ cout<<"A"; } Base(Base& Base){ cout<<"B"; i=Base.i; } operator int() { cout<<"C"; return i; } private: int i; }; int main() { Base obj; obj = obj+obj; return 0; } #包括“stdafx.h” #包括 使用名称空间std; 阶级基础{ 公众: 基数(int m_var=1):i(m_var){ cout,c++,class,operator-overloading,C++,Class,Operator Overloading,操作符int()被调用两次,因为您没有重载操作符+。编译器不知道如何将基添加到基,因此它们被转换为int(因为您教会了它如何做),它知道如何做。下面的代码打印ADA: #include <iostream> using namespace std; class Base { public: Base(int m_var=1):i(m_var){ cout<<"A"; } Base(Base& Base){
操作符int()
被调用两次,因为您没有重载操作符+
。编译器不知道如何将基
添加到基
,因此它们被转换为int
(因为您教会了它如何做),它知道如何做。下面的代码打印ADA
:
#include <iostream>
using namespace std;
class Base {
public:
Base(int m_var=1):i(m_var){
cout<<"A";
}
Base(Base& Base){
cout<<"B";
i=Base.i;
}
operator int() {
cout<<"C";
return i;
}
int operator+(Base& Base)
{
cout<<"D";
return i+Base.i;
}
private:
int i;
};
int main()
{
Base obj;
obj = obj+obj;
return 0;
}
#包括
使用名称空间std;
阶级基础{
公众:
基数(int m_var=1):i(m_var){
cout您可以在表达式obj+obj
中引用obj两次,并且每个这样的引用都必须转换为一个整数
这种转换可能是“有状态的”(stateful),这并非不可能(尽管这是一个可怕的想法),也就是说,通过设计,每次调用它时都会返回不同的值。毕竟,obj
表示的值可能会改变(可能是计数器或类似的东西)因此编译器必须为每个引用重新计算它。每个操作数调用它一次,不管它是否是同一个实例
obj = obj+obj;
它将第一个操作数“强制”为int,然后将第二个操作数“强制”为int
如果要避免此隐式强制转换,则需要重载运算符+。它调用运算符int()
两次,因为它需要将两个obj都转换为int,然后才能添加它们。构造对象时,会得到第一个“A”:
当您指定添加obj+obj
时,编译器需要找出一种在obj
上使用+
的方法。由于您没有为Base
重写运算符+
,因此会对等式的每一侧调用到int()
的转换:
obj+obj
这将打印“CC”
然后,您将分配给obj
,它的类型为Base
,因此可以从int()
操作符接受int(i+i
)的构造函数将运行,并打印“A”:
首先,这一行:
Base obj;
Base obj;
obj = obj + obj
默认值通过选择接受整数的构造函数来构造对象obj
,默认值为1
。这负责将第一个A
打印到标准输出
obj = obj+obj;
^^^--------obj converted to int here
^^^----obj converted to int here
^^^^^------------Base(int) ctor and default operator= called here
然后,这个表达式:
obj + obj
需要选择一个可行的重载运算符+
。在这种情况下,由于obj
有一个用户定义的到int
的转换,因此选择内置的运算符+
,并将两个参数转换为int
。这负责将两个C
打印到标准输出
obj = obj+obj;
^^^--------obj converted to int here
^^^----obj converted to int here
^^^^^------------Base(int) ctor and default operator= called here
然后,在以下步骤中分配给obj
:
obj = obj + obj
需要为Base
调用隐式生成的运算符=
。隐式生成的运算符=
具有签名:
Base& operator = (Base const&);
这意味着等号右侧的表达式(类型为int
)必须转换为临时Base
对象,从中分配obj
(隐式生成的运算符=
的引用参数绑定到此临时对象)
但是从int
创建这个临时文件反过来需要调用Base
的转换结构,它再次接受int
,这负责将第二个A
打印到标准输出
obj = obj+obj;
^^^--------obj converted to int here
^^^----obj converted to int here
^^^^^------------Base(int) ctor and default operator= called here
除非您了解成本,并且知道在您的特定情况下,收益大于成本,否则重载cast操作符通常不是一个好主意。第一个a来自
Base obj;
这两个Cs来自于将obj+obj
中的obj转换为int
,因为您没有重载操作符+
最后一个A来自结果int
到obj
的obj=
转换
< C++程序如何计算“ACCA”?< /P>
显示的第一个字母是“A”。此输出与此行相关:
Base obj;
Base obj;
obj = obj + obj
…您正在其中创建新的Base实例
下一行有点复杂:
obj = obj+obj;
通常,这会转换为obj.operator+(obj)
,但在类Base
中没有重载operator+,因此此转换无效。剩余的可能性是operator+实际上是数字加法运算符
是的,这是可能的,因为您提供了对int
的转换。因此可以在int
中转换方程的每个项……因此运算符int
被调用两次。调用运算符int
的实际次数取决于激活的优化。例如,编译器可以意识到这两个术语是相同的,然后在第一次调用运算符int
后创建一个新的临时值。在这种情况下,您将看到CA而不是CC
最后,赋值表达式obj.operator=(temp)
被执行。这里的关键字是temp。为了让操作符=
工作,因为它没有重载,你必须在右边有一个Base
对象。实际上可以有它,因为Base
使用int
来构建新实例。好的,obj+o的结果是这样的bj
是一个int
(假设它被称为'x')号,编译器创建了一个类Base
的临时对象,该对象是用数字x构造的,如下所示:
Base temp( x );
这就是看到的最后一个字母是“A”的方式。同样,许多编译器可以避免在某些情况下构建临时字母,因此在结尾处可能看不到“A”
请注意,这一行:
Base obj;
Base obj;
obj = obj + obj
因此分解为:
int x = ( (int) obj ) + ( (int) obj );
Base temp( x );
obj = temp;
最终指令的结果就像备忘录一样