2016-03-07 53 views
-1

困惑的模板,我有以下類和編譯器(微軟的Visual Studio 2012)給了我奇怪的結果,因爲是沒有問題的編譯a*v但在編譯b*v我得到以下錯誤:編譯器派生

"error C2678: binary '*': no operator found which takes a right-hand operator of type const double (or there is no acceptable conversion).

對於a*v,編譯器不使用A::operator*(),但對於b*v,使用函數operator*(U t, Vector<T> v)

那麼,有誰知道發生了什麼?

template <class T> 
class Vector 
{ 
public: 
    Vector() { v[0] = 1; v[1] = 2; v[2] = 3; } 
    Vector(T a, T b, T c) { v[0] = a; v[1] = b; v[2] = c; } 
    T v[3]; 
}; 

template <class T, class U> 
Vector<U> operator*(const T& t, const Vector<U>& v) 
{ 
    return Vector<U>(t*v.v[0], t* v.v[1], t*v.v[2]) 
} 

class A 
{ 
public: 
    Vector<double> operator *(const Vector<double>& v) 
    { 
     return Vector<double>(99.0,99.0,99.0); 
    } 
}; 

class B : public A { }; 

void MyFct() 
{ 
    Vector<double> v; 
    A a; 
    B b; 
    Vector<double> test1 = a * v; 
    Vector<double> test2 = b * v; 

    printf("%f %f", test1.v[0], test2.v[0]); 
} 
+0

我不太確定如果我在錯誤信息之後得到了問題描述,如果沒有,請編輯問題以解決問題。 –

+0

我懷疑這會對創建錯誤造成影響,因爲你沒有#include 但是Vector已經是C++中的一個類了,我把你的類與預先存在的Vector類混淆了一分鐘。 – star2wars3

+1

@ star2wars3標準類是小寫字母,'#include '不是一個東西。但我同意這個名字很混亂。 –

回答

0

這不是視覺工作室的問題。鏗鏘提出了同樣的錯誤。應該使用哪個重載操作符是不明確的。它出現在派生類的情況下,選擇了自由運算符*()而不是成員運算符*()。

的 「容易」 的解決方案是:

Vector<double> test2 = b.A::operator*(v); 

更好的解決方案,IMO,是不申報的operator *()作爲成員函數。而是重載免費的運營商模板定義。

0

我在回答我自己的問題。通過限制僅爲算術值創建的返回值,我能夠使編譯器選擇正確的功能

現在,使用以下自由函數,它將僅存在於算術值,並且不會爲類創建A和B.

template <class T, class U> 
inline Vector<typename std::enable_if<std::is_arithmetic<T>::value, U>::type> operator*(const T& t, const Vector<U>& v) 
{ 
    return Vector<U>(v[0]*t, v[1]*t, v[2]*t); 
}