重载运算符以允许在C ++中使用不同的参数顺序

时间:2018-01-19 13:50:48

标签: c++ operator-overloading operators

让我们说我正在编写一个类来表示计算机图形应用程序的3D矢量。我希望能够通过标量乘以向量,如下所示:

Vector3D vec(1, 2, 3);  // The paramaters of the constructor are the x, y and z values
Vector3D vec1 = vec * 2; // Case A: result should be (2, 4, 6)
Vector3D vec2 = 2 * vec; // Case B: result should be (2, 4, 6)

为了使案例A有效,我可以将以下函数添加到我的类中:

class Vector3D
{
public:
    // ...
    const Vector operator*(int scalar) const;
};

为了使案例B有效,我必须在班级之外创建一个函数:

const Vector operator*(int scalar, const Vector& vec);

请注意,我还可以通过在我的课外添加以下函数来使案例A工作:

const Vector operator*(const Vector& vec, int scalar);

我的问题是:最干净的方法是什么?我可以在我的类中添加一个函数,在它之外添加一个函数,或者我可以在我的类之外添加两个函数。我喜欢在类之外添加两个函数的想法,因为我可以让它们彼此相邻,我认为它们更清楚,因为它们基本上做同样的事情,但是在类中添加一个函数有任何好处,我我没有看到?

请注意,我的函数的返回值是const,因此用户无法执行此操作(正如Scott Meyers在他的“Effective C ++”一书中所解释的那样):

Vector3D vecA(1, 2, 3);
Vector3D vecB(1, 2, 3);
Vector3D vecC(1, 2, 3);

vecA * vecB = vecC;

3 个答案:

答案 0 :(得分:2)

通常的方法是提供operator *=(int)作为成员函数,然后编写调用它的自由函数operator*(Vector3D, int)operator*(int, Vector3D)

答案 1 :(得分:1)

由于向量乘以标量是对称的,在某种意义上说没有明确的“上级”或“从属”参与者,我会使用一对独立的运算符重载:

const Vector operator*(int scalar, const Vector& vec);
const Vector operator*(const Vector& vec, int scalar);

当您在重载成员函数与重载独立函数之间做出选择时,决策应该基于对象本身参与计算中与函数参数的关系。

当对象扮演核心角色时,虽然参数扮演外围角色,但通过使其成为成员来保持对象的功能。当对象和函数参数起类似作用时,即参与者之间存在一定程度的对称性时,独立函数更合适。

答案 2 :(得分:1)

operator*这里是对称的(如a * bb * a应该是等效的操作)所以你应该更喜欢让这两个函数在类之外。

除了你提到的内容 - 让它们彼此靠近使它更清晰 - 它还允许对任一操作数进行隐式转换。另一方面,如果您将案例A的operator*作为成员函数,则不允许将左侧操作数隐式转换为Vector3D类型,而是将右侧操作数转换为{{允许1}}类型(除非您标记构造函数Vector3D,但除了该点之外)。

通过使用双重非成员函数,我们具有真正的对称性,因为两个操作数具有相同的转换为explicit类型的能力。

顺便说一句,C++ Core Guidelines written by Bjarne Stroustrup and Herb Sutter也建议这样做。