2013-09-05 79 views
0

我的練習考試任務中有一個小問題。這是一個文本:在C++中重載運算符+

類MyFloat有一個私有變量float num。您必須編寫能夠啓用下一行代碼的方法: MyFloat x = 3.5; MyFloat Y = X + 3.2 浮動Z = 3.4 + Y

而我寫這篇文章的代碼:

#include <iostream> 
#include <Windows.h> 
using namespace std; 

class MyFloat 
{ 
    float num; 
public: 
    MyFloat(float n) 
    { 
     num = n; 

    } 
    MyFloat operator+(MyFloat x) 
    { 
     float result; 
     result = x.num + this->num; 
     return result; 
    } 
}; 

int main() 
{ 
    MyFloat x = 3.75; 
    MyFloat y = x + 3.2; 
    float z = 3.4 + y; 
    system("PAUSE"); 
} 

我得到的錯誤在這行:

float z = 3.4 + y; 

它說:

錯誤C2677:binary'+':no global op erator發現需要輸入'MyFloat'(或者沒有可接受的轉換)

我該怎麼辦?如何解決這個問題呢???

+3

你需要做'+'非成員函數。 –

+0

你可以讓一個非成員操作符重載 – IdeaHat

+0

這已經有一段時間了,因爲我已經在C++中完成了操作符重載,但是他不能僅僅執行'MyFloat操作符+(float x){return num + x; }'?他將一個本地'float'添加到'MyFloat'實例。 – crush

回答

5

這可能是一個解決辦法:

class MyFloat 
{ 
    float num; 
public: 
    MyFloat(float n) 
    { 
     num = n; 
    } 

    operator float() const { 
     return num; 
    } 
}; 

int main() 
{ 
    MyFloat x = 3.75; 
    MyFloat y = x + 3.2f; 
    float z = 3.4f + y; 
} 

起初,我也不過有關使MyFloat operator+(MyFloat, MyFloat)非會員朋友的功能,但它仍然不令而行

float z = 3.4 + y;

到編譯。原因是3.4 + y將是MyFloat類型,因此除非您提供從MyFloatfloat的轉換運算符,否則不能將其分配給float z。但是,3.4f + y變得模糊不清(至少對於VS 2010),因爲它可以調用MyFloat operator+(MyFloat, MyFloat),或者它可以將y轉換爲float,並使用內置運算符+代替float

+0

這工作...非常感謝你! –

+0

這有效(這就是爲什麼我upvoted的答案),但我認爲重要的是要注意,有些情況下你不想這樣做。例如,如果「MyFloat」的範圍大於「float」(http://crd-legacy.lbl.gov/~dhbailey/mpdist/),則將「MyFloat」實例轉換爲「float」會導致您失去這個優勢。 –

+0

這是一個好主意,使用轉換..只是要小心,當你有時使用它... – texasbruce

6

執行operator+作爲非成員朋友函數與2個參數MyFloat operator+(MyFloat x, MyFloat y)

爲什麼它在當前版本中不起作用?因爲成員操作符函數在操作符左側的對象上被調用。在你左邊的情況下,你有整數字面值不是一個對象,所以缺少MyFloat operator+(MyFloat x)成員函數。

操作符的非成員變體是對稱的,並且不要求左側是對象。對稱性是重要的,因爲正如你在例子中看到的,因爲我們曾經認爲在數學


編輯operator+不是對稱的:但這仍然不夠,通過凱西奧內裏在評論中所指出。爲什麼?請參閱他的回答以獲得解釋,但總之:您有模棱兩可的問題。你可以使用他的解決方案或這個如果你手動鑄造像這樣:float z = 3.4f + static_cast<float>(y);這是相當醜陋的。如果您提供MyFloat::operator float轉換,您可以使用另一種演員:float z = MyFloat(3.4f) + y。解決相同歧義問題的另一種解決方案:在C++ 11中,您可以使用自己的後綴文字(類似於內置浮動的f前綴,例如3.4_f;(下劃線表示該後綴文字是用戶自定義的, 。定義)樣品實現(因爲要實現運營商鑄造從MyFloatfloat和向後:

MyFloat operator "" _f(long double val) { 
    return MyFloat(static_cast<float>(val)); } 

int main() { 
    MyFloat x = 3.75; 
    MyFloat y = x + 3.2; 
    float z = 3.4_f + y; 
} 
+0

你的回答清除了我上面的評論。謝謝。 – crush

+0

好意,但它不會使行'float z = 3。4 + y;'編譯。在我的文章中查看爲什麼。 –

+0

我的主要觀點是'MyFloat操作符+(MyFloat,MyFloat)'返回一個'MyFloat'。因此,表達式「3.4 + y」的類型爲「MyFloat」。因此,除非有從'MyFloat'到'float'的轉換運算符,否則它不能被分配給'float'(在'float z = 3.4 + y'中)。的確,'3.4'是一個'double'文字,當它被分配給'float'時,編譯器會產生一個(相當惱人的)警告,但這仍然是合法代碼。 –

3

你只有MyFloat +浮動操作,你需要定義浮動+ MyFloat操作了。他們不是AME。

添加到您的公共職能:

friend float operator+ (const float& lhs, const MyFloat& rhs); 

而這個外部類:

float operator+ (const float& lhs, const MyFloat& rhs) { 
    return lhs + rhs.num; 
} 

注:通過CassioNeri市價修改意見。

+0

幾乎!唯一的問題是通過引用無法綁定到右值的參數。採取價值或參考常量。 –

+0

@CassioNeri編輯.. – texasbruce

+0

然後+1爲您的帖子。 –

0

儘管您可以在定義「強制轉換爲浮動」方法時繼續進行回答,但我相信爲了您自己的利益,您開始利用公共API來實現其他行爲會更好。

一般來說,一個簡單的「鑄造」不會訣竅(例如,如果MyFloatMyMatrix?會發生什麼?)。

下面的方法肯定比較冗長,但它強調你應該「吃自己的食物」,這意味着你應該嘗試基於你自己的公共接口來實現額外的行爲,而不是一堆晦澀的隱式演員,或friend功能。如果您使用自己的API:您將瞭解其侷限性,並且如果您進行修改,可能會節省重新編譯主類。

另外,假設你想要計算對你的類的訪問(或者控制對基礎值的訪問):使用鑄造操作符,你需要複製operator float()float value()中的代碼。

所以,這裏是我的卑微的建議,它似乎更長,但根據我的口味,更好地反映了面向對象的設計原則。

#include<iostream> 

class MyFloat { 

public: 
    MyFloat(float value): 
     m_value(value) { } 

    float value() const { 
    return m_value; 
    } 

private: 
    float m_value; 

}; 

// Eat your own food: implement functions using your public interface 
// until proven need to do otherwise. This will help you assess the 
// usability of your API. 
float operator+(const MyFloat& lhs, const MyFloat& rhs) { return lhs.value() + rhs.value(); } 
float operator+(const MyFloat& lhs, float rhs) { return lhs.value() + rhs; } 
float operator+(float lhs, const MyFloat& rhs) { return lhs + rhs.value(); } 

// See, now I can define another operator without need to recompile my 
// class (this could have been placed in another file) 
std::ostream& operator<<(std::ostream& os, const MyFloat& mf) { 
    os<<"MyFloat("<<mf.value()<<")"; 
    return os; 
} 

int main() { 

    MyFloat x = 3.5;  // would not work if I had declared the constructor as "explicit" 
    MyFloat y = x + 3.2; 
    MyFloat z = 3.4 + y; 

    std::cout<<x<<", "<<y<<", "<<z<<std::endl; 
} 

輸出(帶g++ example.cpp -Wall -Wextra編譯):

MyFloat(3.5), MyFloat(6.7), MyFloat(10.1)