将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数

Constructors for Automatic Type Conversion when passing a built-in type variable to a "+" operator function having only one class-type argument

本文关键字:运算符 函数 构造函数 类型转换 类型参数 类型变量 内置 有一个      更新时间:2023-10-16

我有以下代码:

#include <iostream>
using namespace std; 
class test {
public:
test() {
for (int i = 0; i < 5; i++)
this->arr[i] = 0; 
}
test(int val) {
for (int i = 0; i < 5; i++)
this->arr[i] = val;
}
test(int* a) {
for (int i = 0; i < 5; i++) 
this->arr[i] = a[i]; 
}
test operator +(test& sub) {
int arr1[5];
for (int i = 0; i < 5; i++) {
arr1[i] = this->arr[i] + sub.arr[i];
}
return test(arr1);
}
void display() {
cout << "The array is: "; 
for (int i = 0; i < 5; i++) {
cout << this->arr[i] << "t"; 
}
}
private: 
int arr[5];
};
int main() {
int x = 5;
test obj1(5), obj2(1); 
obj2 = obj1 + x; //Error here
obj2.display();
return 0; 
}

它试图通过添加两个对象的"arr"成员变量来测试重载"+"运算符,返回一个带有结果的对象并将其分配给主函数中的obj2。然而,根据《绝对C++》一书,也可以像现在这样,通过首先通过"test"类中的构造函数将整数转换为"test"类型,因为该构造函数接受整数类型的变量作为其参数。然后,值为"x"的结果对象将被传递给"+"函数,它将正常工作。

但是,代码无法编译,我尝试此操作时收到错误:没有与这些操作数匹配的"+"运算符。那么,我的代码在解释这本书的细节时可能有什么问题呢?

出现编译错误的原因是operator+接受非常量左值引用。

如果更改运算符的签名以采用const test&它将能够绑定到右值,这将进行编译。

test operator +(const test& sub) {
...
}

由于该方法不会修改sub因此它应该采用 const-ref。

编辑:由于值类别,const关键字在这里产生了重要差异。首先,让我们看一个简单的例子。

void foo(int& i) {
i = 5;
}
int b;
foo(b); //this is ok
foo(7); //this is not ok

我们指定我们想要一个左值引用。这意味着我们可以传入变量,但不能传入临时变量。在这种情况下,临时是文字,但它也可能是另一个函数的返回值。

如果我们回到你的问题,当你写obj1 + x时,你已经意识到发生了从inttest的转换。该转换的返回值是一个临时值。

如果我们想处理右值(临时(,我们需要使用右值引用。

void foo(int&& i) {
i = 5;
}
int x;
foo(x); // Now this will fail instead
foo(5); // This will however work

当我们使用const&时,我们是在说我们不会修改该值,并且由于我们已经承诺不修改它,因此它是否是临时的并不重要。无论如何,我们只会从中阅读。

这就是为什么const&可以绑定到左值或右值的原因。

void foo(const int& i) {
std::cout << i;
}
int x = 7;
foo(x); // This will work
foo(17); // This will also work