#include<iostream>
using namespace std;
class test
{
int a, b;
public:
test() {
a=4; b=5;
}
test(int i,int j=0) {
a=i; b=j;
}
test operator +(test c) {
test temp;
temp.a=a+c.a;
temp.b=b+c.b;
return temp;
}
void print() {
cout << a << b;
}
};
int main() {
test t1, t2(2,3), t3;
t3 = t1+2;
t3.print();
return 0;
}
编译器如何接受t3=t1+2;
之类的语句,其中2
不是对象?
答案 0 :(得分:7)
编译器发现您正在调用operator+(test)
并尝试使用您的2
构造函数隐式将test
转换为test(int i,int j=0)
。
如果要显式转换,则必须将构造函数更改为explicit test(int i, int j=0)
。在这种情况下,您的代码会生成编译器错误,因为2
无法隐式转换为test
。您需要将表达式更改为t1 + test(2)
。
答案 1 :(得分:2)
因为test(int i,int j=0)
是一个带有一个或两个参数的构造函数,所以从test
创建了一个2
对象。在下一阶段test operator +(test c)
被调用。
答案 2 :(得分:2)
有一个二进制operator+
可用,它接受两个类型为test
的操作数。此外,test
可以通过构造函数int
从test(int, int = 0)
隐式构造。将两者放在一起,t1 + 2
变为t1 + test(2, 0)
。
要禁止此静默转换(有时可能导致非常令人惊讶的转换链),请声明您的构造函数接受一个明确的参数:explicit test(int, int = 0)
。
答案 3 :(得分:1)
因为test(int i, int j = 0)
未标记为显式。
因此t1 + 2
被解释为t1.operator+(2)
,它本身被解释为t1.operator+(test(2))
(隐式转化)。
如果您将构造函数标记为explicit
,则会出现错误(在编译期间),说2
无法转换为test
或operator+
不匹配。
答案 4 :(得分:0)
简而言之,因为C ++包含运算符重载,所以能够为用户定义的类型定义运算符的自定义实现。上面显示的operator+()
函数是您为类型+
定义test
运算符的方式。当编译器看到+
应用于test
对象的表达式时,它会查找operator+
中定义的test
(或定义为test
的双参数形式具有类型test&
或{{1}}的第一个参数的全局函数。)然后它可能在转换另一个参数之后调用该函数。
答案 5 :(得分:0)
因为您的构造函数test(int i,int j=0)
引入了从int
到test
的用户定义转换。
答案 6 :(得分:0)
编译器使用其构造函数创建一个Test类型的对象。
t3 = t1 + test(2);