让我们说我正在编写一个类来表示计算机图形应用程序的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;
答案 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 * b
和b * a
应该是等效的操作)所以你应该更喜欢让这两个函数在类之外。
除了你提到的内容 - 让它们彼此靠近使它更清晰 - 它还允许对任一操作数进行隐式转换。另一方面,如果您将案例A的operator*
作为成员函数,则不允许将左侧操作数隐式转换为Vector3D
类型,而是将右侧操作数转换为{{允许1}}类型(除非您标记构造函数Vector3D
,但除了该点之外)。
通过使用双重非成员函数,我们具有真正的对称性,因为两个操作数具有相同的转换为explicit
类型的能力。
顺便说一句,C++ Core Guidelines written by Bjarne Stroustrup and Herb Sutter也建议这样做。