0

请花点时间查看下面的代码并回答我的问题

class Vector
{
public:
    int x, y;
    /* Constructor / destructor / Other methods */
    Vector operator + (Vector & OtherVector);
    Vector & operator += (Vector & OtherVector);
};

Vector Vector::operator + (Vector & OtherVector)  // LINE 6
{
    Vector TempVector;
    TempVector.x = x + OtherVector.x;
    TempVector.y = y + OtherVector.y;
    return TempVector;
}

Vector & Vector::operator += (Vector & OtherVector)
{
    x += OtherVector.x;
    y += OtherVector.y;
    return * this;
}

Vector VectorOne;
Vector VectorTwo;
Vector VectorThree;

/* Do something with vectors */
VectorOne = VectorTwo + VectorThree;
VectorThree += VectorOne;

该代码是从一本书中摘录的,但其中没有很好地解释。具体来说,我无法理解第 6 行的程序。构造函数和运算符都没有重载。请解释操作符重载和复制构造函数在这个程序中是如何工作的。

编辑:为什么我们使用引用运算符?

4

5 回答 5

1

此代码不包含复制构造函数,但是复制构造函数用于动态分配类成员的场景,因此一旦实例或对象超出范围,程序不应崩溃,因为析构函数将释放动态分配的如果您分别为 new 或 malloc 包含 delete 或 free ,则内存。

现在来到第 6 行的运算符重载:当您添加到对象时

VectorOne = VectorTwo + VectorThree;

调用第 6 行函数,它创建临时对象以对 VectorTwo 和 VectorThree 的成员进行加法,然后将临时对象返回给 VectorOne,因此 VectorOne 接收 TempVector 的按位副本。. 请记住,VectorTwo 被隐式传递给此函数,因为它位于重载运算符的左侧当您添加对象时VectorThree += VectorOne;,会调用函数 operator+=() 并将 VectorThree 隐式传递给该函数,然后该函数返回按位副本隐式传递给函数的对象。关键字this指向在本例中为 VectorThree 调用函数的对象。然后返回的副本再次保存在 VectorThree 中。

于 2012-07-12T17:16:03.990 回答
1

第 6 行重载了“+”运算符,而第 14 行重载了“+=”运算符。例如:

Vector v1,v2,v3;

v1 += v2; // Line 14 takes care of this one

v3 = v1 + v2; // Line 6 takes care of this one

这里最大的区别是“+=”重载修改了调用该运算符的实例中的值(上例中的v1),而“+”运算符采用两个实例并使用修改后的值生成第三个实例. 希望这很清楚。

于 2012-07-12T16:50:02.390 回答
1
6:   Vector operator + (Vector & OtherVector);
7:   Vector & operator += (Vector & OtherVector);

那些声明运算符重载。它们对于表明您确实想要重载运算符是必要的。更多关于下面的返回值:

10: Vector Vector::operator + (Vector & OtherVector)
11: {
12:  Vector TempVector;
13:  TempVector.x = x + OtherVector.x;
14:  TempVector.y = y + OtherVector.y;
15:  return TempVector;
16: }

返回 TempVector 的副本,它添加了向量的 x 和 y 分量。这允许以下用法(前提是还定义了赋值运算符:

24: Vector VectorOne;
25: Vector VectorTwo;
26: Vector VectorThree;
27: /* Do something with vectors */
28: VectorOne = VectorTwo + VectorThree;

17: Vector & Vector::operator += (Vector & OtherVector)
18: {
19:  x += OtherVector.x;
20:  y += OtherVector.y;
21:  return * this;
22: }

这与上面的相同,只是我们添加到调用实例而不是临时变量的细微差别。这导致返回*thisthis是指向该类的当前实例的指针,因此为了获得它的值,您需要使用星号取消引用运算符(如果我对运算符的名称有误,请纠正我)。

于 2012-07-12T16:41:11.220 回答
1

创建 Vector 类的operator+新实例,将两个输入的 x 和 y 元素之和放入该新实例,然后返回新实例。至少国际海事组织(我无法想象有很多人不同意)最好写成这样的:

Vector Vector::operator+(Vector const &otherVector) const {
    // ...
}

...将函数本身及其正确输入限定为const,因为它不打算修改任何一个。函数的限定条件基本上是指左操作数,所以这基本上是说当我们执行类似 的操作时a = b + c;,既b不会也c不会被修改(即,正是您通常所期望的)。这允许(除其他外)将类型的临时对象Vector用作操作数,并确保您不会无意中修改输入。

operator+=修改它的左操作数,所以它只是将另一个向量中的 x 和 y 元素添加到自身。然后它返回对作为左操作数提供的操作数(修改版本)的引用。这允许运算符链接,例如:

Vector a, b, c;

// code to initialize a, b and c here

a += (b += c);

同样,它会受益于通过引用 const 来获取输入:

Vector &Vector::operator+=(Vector const &other) {
    // ...
}

在这种情况下,我们不能(也不想)const限定函数本身,因为它确实修改了它的左操作数(再次,正是你所期望的:在 中a += b,我们期望a改变并b保持不变)。

至少正如您所展示的,类定义不包含显式复制构造函数,这意味着如果您复制此类的对象,编译器将为您合成一个复制构造函数。在应该没问题的情况下——类中唯一的数据是两个整数,这通常可以用于成员副本(这是编译器将生成的)。显式复制构造函数的最常见原因是一个类包含一个或多个指向它所拥有的对象的指针(在这种情况下,您还希望看到三/五的规则)。

于 2012-07-12T16:41:21.630 回答
0

第 6 行和第 7 行是重载运算符的原型。

Vector & operator += (Vector & OtherVector);

返回类型是向量引用,参数是向量引用。运营商就是+=运营商。该函数将在以下行调用:

VectorThree += VectorOne;

定义在第 17 行。您可以看到它们的行为与典型的成员函数相同(它们有一个this常量,隐式用于定位 x 和 y)。作为典型的 += 运算符,该函数的工作方式是参数的内容VectorOne保持不变,并将 的内容VectorThree设置为其原始值 plus VectorOne,并返回新的值 of VectorThree。您可以自己验证整数类型的 += 运算符是否以与以下代码段相同的方式工作:

int a = 1, b = 2, c;
c = (a += b);
cout << "a: " << a << " b: " << b << " c: " << c << endl;

重要的是要注意,类的运算符的实现可以遵循他们想要的任何模型。例如,字符串的 += 运算符是就地追加运算符。一般来说,如果一个类定义了一个 + 运算符和一个 += 运算符,+ 运算符将接受 2 个参数,执行一些操作,并返回第三个值,而 += 运算符将接受 2 个参数,执行一些操作,修改其参数之一,并返回该值。

同样重要的是要注意,由于两个运算符的参数值都没有改变,您可以将它们设为 const,如下所示:

Vector operator + (const Vector & OtherVector);
Vector & operator += (const Vector & OtherVector);

这样做的原因是,如果你想将一个 const 变量传递给一个没有声明其参数 const 的运算符,你将无法做到,即使它没有更改它们。如果没有为 += 的参数指定 const,则以下内容是非法的,如果是,则合法:

Vector value1;
const Vector value2;

value1 += value2;
于 2012-07-12T16:42:01.967 回答