2013-03-15 372 views
15

我正在學習C++,並創建了兩個簡單的hello-world應用程序。在他們兩人中,我使用操作員超載,但這是問題所在。在第一個,我可以提供兩個參數來重載運算符,並沒有問題。C++中運算符重載的參數個數

標題:

enum Element {a,b,c,d,e}; 
Element operator + (Element x, Element y); 
//more overloads for -, *,/here 

來源:

Element operator + (Element x, Element y) { 
    return ArrayOfElements[x][y]; 
} 

但在我的第二應用(簡單的複數計算器) - 此方法不起作用。谷歌搜索,並弄清楚爲什麼後,我結束了這段代碼:

標題:

struct Complex { 
     double Re; 
     double Im; 

     Complex (double R, double I) : Re(R), Im(I) { } 

     Complex operator + (Complex &Number); 
     //more overloads 
    }; 

來源:

Complex Complex::operator + (Complex &Number) 
    { 
     Complex tmp = Complex(0, 0); 
     tmp.Re = Re + Number.Re; 
     tmp.Im = Im + Number.Im; 
     return tmp; 
    } 

它的工作了,但我想知道,爲什麼在第一段代碼中,我被允許將兩個參數放在operator重載中,但是第二個代碼中出現了以下錯誤?

complex.cpp:5:51: error: 'Complex Complex::operator+(Complex, Complex)' must take either zero or one argument 

每當我使用類或不使用類時都是如此。我一直在尋找許多文檔,第二種方式似乎更加正確。也許這是因爲不同的參數類型?

使用g++編譯的-Wall -pedantic參數的兩個源都使用相同的庫。

+5

成員函數有一個隱含的'this'參數 – 2013-03-15 20:43:48

回答

24

假設你有一個這樣的類:

class Element { 
public: 
    Element(int value) : value(value) {} 
    int getValue() const { return value; } 
private: 
    int value; 
}; 

有四種方法來定義一個二元運算符,如+

  1. 與只能訪問類的public構件的自由功能:

    // Left operand is 'a'; right is 'b'. 
    Element operator+(const Element& a, const Element& b) { 
        return Element(a.getValue() + b.getValue()); 
    } 
    

    e1 + e2 == operator+(e1, e2)

  2. 作爲成員函數,與訪問類的所有成員:

    class Element { 
    public: 
        // Left operand is 'this'; right is 'other'. 
        Element operator+(const Element& other) const { 
         return Element(value + other.value); 
        } 
        // ... 
    }; 
    

    e1 + e2 == e1.operator+(e2)

  3. 作爲friend功能,具有訪問類的所有成員:

    class Element { 
    public: 
        // Left operand is 'a'; right is 'b'. 
        friend Element operator+(const Element& a, const Element& b) { 
         return a.value + b.value; 
        } 
        // ... 
    }; 
    

    e1 + e2 == operator+(e1, e2)

  4. 如行爲以外類體完全相同的定義爲#3 friend功能:

    class Element { 
    public: 
        friend Element operator+(const Element&, const Element&); 
        // ... 
    }; 
    
    Element operator+(const Element& a, const Element& b) { 
        return a.value + b.value; 
    } 
    

    e1 + e2 == operator+(e1, e2)

+3

如果它是一個成員函數,你可以做'Element(2)+ 3',而不是'2 + Element(3)'。 – aschepler 2013-03-15 20:49:43

+0

我在第一個課堂上沒有任何課程(僅在第二個課程中),但是感謝您的出色答案! – Lemurr 2013-03-15 21:59:12

1

如果您希望operator+需要兩個操作數顯式參數,它必須定義爲一個自由(即非會員)功能:

class Complex { 
    friend Complex operator+(const Complex& lhs, const Complex& rhs); 
} 

Complex operator+(const Complex& lhs, const Complex& rhs) { 
    ... 
} 

使用這種形式,如果左操作數是原始類型,或者是您不能控制的類(因此不能添加成員函數)。

+2

...並且如果可能存在任何到Complex的隱式轉換,您應該使用此表單。 – aschepler 2013-03-15 20:48:47

4

由於+是一個二元運算符,如果您在結構體/類中重載它,則只能提供一個操作數,原因是第一個操作數隱含地是調用對象。這就是爲什麼在第一種情況下,你有兩個參數,因爲它超出了你的類/結構體的範圍,而在第二種情況下,它作爲成員函數被重載。

1

如果重載函數是一個成員函數的類,則我們通過只有一個參數,且有一個指向以執行像「二進制運算所需要的其他對象的一個​​隱藏的參數(指針)+ 」。 This指針指向其中一個操作數並調用重載函數;而其他操作數作爲參數傳遞。 實施例:

class ExampleClass 
{ 
public: 
    int x; 
    //a this pointer will be passed to this function 
    ExampleClass& operator+(const ExampleClass& o){ return x+o.x; } 
}; 



ExampleClass obj1, obj2, obj; 
obj = obj1 + obj2; //the overloaded function is called as obj1.operator+(obj2) internally 
        //this pointer is passed to the function 

當重載函數不是一個成員函數(無論是自由函數或朋友功能),則我們沒有提供給重載函數的指針。在這種情況下,編譯器需要兩個用作操作數的函數參數。

class ExampleClass 
{ 
    public: 
     int x; 
     //this pointer will not be passed to this function 
     friend ExampleClass& operator+(const ExampleClass& o1, const ExampleClass& o2){ return o1.x+o2.x; } 
}; 



obj = obj1 + obj2; //the overloaded function is called as operator+(obj1, obj2) internally 
0

E1 + E2 == e1.operator +(E2)。這意味着E1是一個對象和操作員+是一個構件和e2是作爲可變.basicaly糟糕允許我們做只寫E1 + E2編譯器自動理解作爲e1.operator +(e1)