当前位置:嗨网首页>书籍在线阅读

13-为Vector类重载算术运算符

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

11.5.2 为Vector类重载算术运算符

在使用x、y坐标时,将两个矢量相加将非常简单,只要将两个x分量相加,得到最终的x分量,将两个y分量相加,得到最终的y分量即可。根据这种描述,可能使用下面的代码:

Vector Vector::operator+(const Vector & b) const
{
    Vector sum;
    sum.x = x + b.x;
    sum.y = y + b.y;
    return sum; // incomplete version
}

如果对象只存储x和y分量,则这很好。遗憾的是,上述代码无法设置极坐标值。可以通过添加另外一些代码来解决这种问题:

Vector Vector::operator+(const Vector & b) const
{
    Vector sum;
    sum.x = x + b.x;
    sum.y = y + b.y;
    sum.set_ang(sum.x, sum.y);
    sum.set_mag(sum.x, sum.y);
    return sum; // version duplicates needlessly
}

然而,使用构造函数来完成这种工作,将更简单、更可靠:

Vector Vector::operator+(const Vector & b) const
{
    return Vector(x + b.x, y + b.y); // return the constructed Vector
}

上述代码将新的x分量和y分量传递给Vector构造函数,而后者将使用这些值来创建无名的新对象,并返回该对象的副本。这确保了新的Vector对象是根据构造函数制定的标准规则创建的。

提示: 如果方法通过计算得到一个新的类对象,则应考虑是否可以使用类构造函数来完成这种工作。这样做不仅可以避免麻烦,而且可以确保新的对象是按照正确的方式创建的。

1.乘法

将矢量与一个数相乘,将使该矢量加长或缩短(取决于这个数)。因此,将矢量乘以3得到的矢量的长度为原来的三倍,而方向不变。要在Vector类中实现矢量的这种行为很容易。对于极坐标,只要将长度进行伸缩,并保持角度不变即可;对于直角坐标,只需将x和y分量进行伸缩即可。也就是说,如果矢量的分量为5和12,则将其乘以3后,分量将分别是15和36。这正是重载的乘法运算符要完成的工作:

Vector Vector::operator*(double n) const
{
    return Vector(n * x, n * y);
}

和重载加法一样,上述代码允许构造函数使用新的x和y分量来创建正确的Vector对象。上述函数用于处理Vector值和double值相乘。可以像Time示例那样,使用一个内联友元函数来处理double与Vector相乘:

Vector operator*(double n, const Vector & a) // friend function
{
    return a * n; // convert double times Vector to Vector times double
}

2.对已重载的运算符进行重载

在C++中,−运算符已经有两种含义。首先,使用两个操作数,它是减法运算符。减法运算符是一个二元运算符,因为它有两个操作数。其次,使用一个操作数时(如−x),它是负号运算符。这种形式被称为一元运算符,即只有一个操作数。对于矢量来说,这两种操作(减法和符号反转)都是有意义的,因此Vector类有这两种操作。

要从矢量A中减去矢量B,只要将分量相减即可,因此重载减法与重载加法相似:

Vector operator-(const Vector & b) const;        // prototype
Vector Vector::operator-(const Vector & b) const // definition
{
    return Vector(x - b.x, y - b.y);             // return the constructed Vector
}

操作数的顺序非常重要。下面的语句:

diff = v1 - v2;

将被转换为下面的成员函数调用:

diff = v1.operator-(v2);

这意味着将从隐式矢量参数减去以显式参数传递的矢量,所以应使用x − b.x,而不是b.x − x。

接下来,来看一元负号运算符,它只使用一个操作数。将这个运算符用于数字(如−x)时,将改变它的符号。因此,将这个运算符用于矢量时,将反转矢量的每个分量的符号。更准确地说,函数应返回一个与原来的矢量相反的矢量(对于极坐标,长度不变,但方向相反)。下面是重载负号的原型和定义:

Vector operator-() const;
Vector Vector::operator-() const
{
    return Vector (-x, -y);
}

现在,operator-()有两种不同的定义。这是可行的,因为它们的特征标不同。可以定义−运算符的一元和二元版本,因为C++提供了该运算符的一元和二元版本。对于只有二元形式的运算符(如除法运算符),只能将其重载为二元运算符。

注意: 因为运算符重载是通过函数来实现的,所以只要运算符函数的特征标不同,使用的运算符数量与相应的内置C++运算符相同,就可以多次重载同一个运算符。