標籤:

為什麼c++不能把「= [] () ->」操作符重載為非成員函數?

我查了一下stackoverflow,大家對於不能把『=』重載為非成員函數的理由主要是因為如果類內未重載『=』操作符,則編譯器會自動合成一個默認的『=』操作符,如果在類外再定義會產生二義性

c++ - Why can"t we overload "=" using friend function?

c++ - Why cannot a non-member function be used for overloading the assignment operator?

但是現在有兩個問題,

1.為什麼會產生二義性?

編譯器所自動合成的默認"="操作符無非是

T operator=(const T)這個樣子的函數,那麼如果我在類外定義一個T operator=(const T, int)這樣的函數,會有二義性嗎?我用『+』操作符做了這個實驗,並沒有出現任何問題:

class foo{
public:
void operator+(const foo tmp){
cout &<&< "member-function" &<&< endl; } }; void operator+(const foo tmp, int i) { cout &<&< "unmember-function" &<&< endl; } int main(int argc, char* argv[]) { foo test; foo test2; test + test2; test + 1; system("pause"); return 0; }

輸出為

「member-function」

「unmember-function」

2. 第二個問題是,怎麼解釋[] -&> ()這三個也不能定義為非成員操作符?


其實把這些操作符弄成非成員函數沒有問題,只不過這些非成員函數能做到的事情成員函數都能做到(operator()和[]除外)。所以允許這些操作符成為非成員函數並不會讓你更加方便地寫代碼。


《C++設計與演化》中提到

如果operator=是全局的,那麼在某些文件中聲明了operator=某些文件沒有聲明,那麼就造成了在不同文件中operator=行為不一致的問題。

至於() -&> [] 書中沒有明確說明,看樣子也是擔心全局的話會造成行為不一致的問題。


換個思路。

如果=, (), -&>和[]能重載為非成員函數,那麼是不是我可以重載operator=(int, T),然後就修改了默認的int賦值語義了?

然後你所有的涉及到int賦值的代碼都會變成一坨屎。

就是這樣。


Operator[] overloading using friend function

As Bjarne Stroustrup says in the Damp;E book:

However, even in the original design of C++, I restricted operators [], (), and -&> to be members. It seemed a harmless restriction that eliminated the possibility of some obscure errors because these operators invariably depend on and typically modify the state of their left-hand operand. However, it is probably a case of unnecessary nannyism

這些話解釋的挺好的


你看這樣理解對不對

因為每個類都隱式地有這幾個運算符的定義,

所以全局函數會被隱式的函數覆蓋掉,

而像+這些符號因為本身沒有定義,

所以聲明為全局函數和成員函數是一樣的


class foo{
public:
void operator+(const foo tmp){
cout &<&< "member-function" &<&< endl; } }; void operator+(const foo tmp, const foo tmp1) { cout &<&< "unmember-function" &<&< endl; } int main(int argc, char* argv[]) { foo test; foo test2; test + test2; //調用成員函數版operator= system("pause"); return 0; }

以上代碼gcc下輸出了 member function,這意味著成員函數版本的重載覆蓋了非成員函數版重載;類推一下,如果你寫了非成員函數的operator=,那麼由於編譯器自動為你在類內寫了一個operator=,造成的結果就是你自定義的operator=得不到執行,因此c++乾脆規定=必須重載為成員函數版本。 另外為什麼[] -&> ()也只能重載為成員函數版,我覺得可能是c++不希望你寫出類似 3(foo) 3-&>foo 這種難以讀懂的代碼吧。 以上是我的猜測,希望大家批評指正。

=============================================================

上面某個答案說operator=(int, T)會修改默認賦值,我不知道是什麼意思,默認賦值不是只有基本類型間才有的嗎?


類賦值操作符必須是類的成員,以便編譯器可以知道是否需要合成一個~


直觀上就是這樣的。對象自己的行為,對象自己決定。難道你要在外面訪問對象的各種信息?有點品味好不


推薦閱讀:

為什麼這些年c語言統治了幾乎所有方面?
怎麼理解 `auto var = [&]() { /* things to do */ }`?
為什麼 C++ 列表初始化時會執行兩次拷貝構造函數?
寫循環語句,循環體部分理論上是不是可以都寫在for(;;)第二個分號後?
map key是一個複雜結構,為什麼無法插入?

TAG:C |