2012-02-06 80 views
7

我有一个困难时期形成的什么,我想问问,所以让我给你举个例子问题重载语法:基本操作在C++中

说我们是一个3D系统,我们有工作定义了一个矢量类Vec3。我们重载一些算术运算符以获得明显的响应。其中,我们重载*运算符,以便它返回两个向量的点积。现在我们的代码看起来应该是这样的:

class Vec3{ 
private: 
    float x, y, z; 
public: 
    float operator*(const Vec3&) const; //dot product 
. 
. 
. 

现在说,我们希望能够通过使用运算符*的东西,以扩展我们的矢量,说一个浮动。这可以通过声明来完成下列操作:

Vec3 operator*(const float) const; 
    friend Vec3 operator*(const float, const Vec3&); 

这yeilds两个重载和我不知道是否有一种方法只有一个做到这一点,也就是说,我们声明,取代上述两行这样的:

friend Vec3 operator*(const Vec3&, const Vec3&); 

然后添加Vec3 ctor的默认值来处理float的转换。

最后一个例子将工作:

Vec3 someVec3 = 1.0 * otherVec3; //through friend Vec3 operator*(const float, const Vec3&) 

但不是这个:

Vec3 someVec3 = otherVec3 * 1.0; 

,因为编译器不知道要使用的两个:

friend Vec3 operator*(const float, const Vec3&); //the one we want to use 
or 
    float operator*(const Vec3&) const; //the one for the dot product 

有什么建议吗?

谢谢!

+3

两个重载有什么问题?正如你所指出的那样,当你试图简化它时,会产生一个相当讨厌的歧义...... – 2012-02-06 17:39:48

+2

我会做不同的唯一的事情,就是使两个版本的标量乘以友元函数,而不是一个成员,这样代码将会与操作本身具有相同的对称性。 – 2012-02-06 17:52:42

+0

构建一个仅仅传递一个浮点数的向量将是低效的。这将会导致运行时效率低下,但可以内联一个额外的重载函数。 – QuentinUK 2012-02-06 17:58:01

回答

5

在这种情况下,我将首先建议不要操作符重载,因为您的使用者知道*代表点或跨产品(两者都是根据预期客户端使用合理的含义)。我实际上建议只是不支持operator*并与dot,crossscale成员一起使用。然后,您不必担心多重过载,并且您的用户很清楚他们获得了什么。

但是,如果您确实想要与操作员一起工作,那么有两个重载没有任何问题。创建一个虚拟Vec3做缩放不仅在语义上不正确,它会添加少量不需要的开销。

1

没有什么错在几个重载的,特别是没有,如果他们可以很容易地在对方的方面来实现:

Vec3 operator*(const float scale, const Vec3& vec) 
{ return vec * scale; } 

这是很难得到它比简单!

2

Boost.Operators可以为你做大部分的锅炉工作。例如: -

class Vec3 
    : boost::multipliable2<Vec3, float> 
{ 
public: 
    // ... 

    Vec3 operator*=(float); 
    // Vec3 operator*(Vec3, const float&) and 
    // Vec3 operator*(const float&, Vec3) auto-generated 
    // by multipliable. 
};