2012-02-06 77 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. 
};