2014-01-19 143 views
1

連接到這個問題的代碼編譯失敗(克++ 4.7)與以下錯誤:朋友聲明*

test.cpp:22:31: error: declaration of ‘operator*’ as non-function 
test.cpp:22:31: error: expected ‘;’ at end of member declaration 
test.cpp:22:32: error: expected unqualified-id before ‘<’ token 
test.cpp: In function ‘int main(int, char**)’: 
test.cpp:39:11: warning: unused variable ‘d’ [-Wunused-variable] 
test.cpp: In instantiation of ‘Vector3<T> operator*(T, const Vector3<T>&) [with T = float]’: 
test.cpp:37:16: required from here 
test.cpp:25:10: error: ‘float Vector3<float>::v [3]’ is private 
test.cpp:30:57: error: within this context 
test.cpp:25:10: error: ‘float Vector3<float>::v [3]’ is private 
test.cpp:30:57: error: within this context 
test.cpp:25:10: error: ‘float Vector3<float>::v [3]’ is private 
test.cpp:30:57: error: within this context 

然而,如果朋友聲明之前所移動的operator*成員聲明/定義(簡單地交換在示例代碼的註釋),那麼它編譯罰款。我不明白爲什麼。有沒有什麼辦法可以使用位於operator*成員聲明之後的朋友聲明來編譯此代碼?

template<typename T> 
class Vector3; 

template<typename T> 
Vector3<T> operator*(T f, const Vector3<T>& v); 

template<typename T> 
class Vector3 { 
public: 
    Vector3(T x, T y, T z) { 
     v[0] = x; 
     v[1] = y; 
     v[2] = z; 
    } 

    //friend Vector3<T> operator*<>(T f, const Vector3<T>& v); // WORKS 

    T operator*(const Vector3<T>& other) const { 
     return (v[0] * other.v[0] + v[1] * other.v[1] + v[2] * other.v[2]); 
    } 

    friend Vector3<T> operator*<>(T f, const Vector3<T>& v); // FAILS 

private: 
    T v[3]; 
}; 

template<typename T> 
Vector3<T> operator*(T f, const Vector3<T>& v) { 
    return Vector3<T>(f * v.v[0], f * v.v[1], f * v.v[2]); 
} 

int main(int argc, char *argv[]) { 
    Vector3<float> v(0, 0, 0); 
    Vector3<float> w(0, 0, 0); 

    w = 2.0f * v; 

    float d = v * w; 

    return 0; 
} 

回答

2

的問題是,你沒有指定你的意思是從全局命名空間的operator *,要做到這一點您的朋友聲明更改爲:

friend Vector3<T> (::operator*<>)(T f, const Vector3<T>& v); 

當你面前的operator *成員宣佈它有沒有歧義,所以它被正確地拾起。

+0

謝謝,現在編譯。但是,成員'operator *'聲明如何來自全局名稱空間的'operator *'映射? – user3146587

+0

更新應該澄清。 – tumdum

+0

@Tomasz:這個規則實際上並沒有。全局命名空間不是「最內層非封閉非類作用域之外」,它*是最內層封閉非類作用域。這就是爲什麼它可以在所有被發現(如果沒有本地運營商'*') –