查看完整版本: 對於C++ class中 operator=() 和 operator=(&)的差別
頁: [1]

在那裡 發表於 2019-3-24 12:20 AM

對於C++ class中 operator=() 和 operator=(&)的差別

本帖最後由 在那裡 於 2019-3-24 12:30 AM 編輯

小弟在寫程式作業時,遇到了一個令我不解的問題:
由於是多檔案實作,程式碼有些長,我附上關鍵的程式碼就好。
使用的環境是Visual Studio 2017

首先是我定義的class
class Month
{
private:
        int month;

        int translateStr(char a, char b, char c);
        std::string translateNum(int num);

public:
        Month() : month(1) {};
        Month(char a, char b, char c);
        Month(int num);
        ~Month() {};

        void setMonth(int mon);
        void setMonth(char a, char b, char c);
        void inputInt();
        void inputStr();
        void inputFirstThreeLetters();
        void outputInt();
        void outputFirstThreeLetters();
        void outputStr();
        Month nextMonth();

        Month& operator=(Month& b); //出問題的函數,改為 Month& operator=(Month b);就沒問題

};


再來是出問題的行數
在main中
int main()
{
        Month month1, month2(2), month3('M', 'a', 'r'), month4, month5, month6;
        //month3並無錯誤。
        
        month4 = month3.nextMonth(); //錯誤行數,訊息為:

        //error C2679: 二元運算子 '=': 找不到使用右方運算元類型 'Month' 的運算子 (或是沒有可接受的轉換)
        //note: 可能是 'Month &Month::operator =(Month &)'
        // note: 當嘗試符合引數清單 '(Month, Month)' 時
        .......
        return 0
}

接下來是函數的實作
Month& Month::operator=(Month& b)
{
        if (&b == this)
        {
                return *this;
        }

        month = b.month;
        return *this;
}


Month Month::nextMonth()
{
        return Month(month + 1);
}


Month::Month(int num)
{
        setMonth(num);
}

void Month::setMonth(int mon)
{
        if (mon <= 0 || mon > 12) //超出range
        {
                month = 1;
        }
        else
        {
                month = mon;
        }
}

為了讓程式碼能正常運作
附上Month3所使用的建構函數
Month::Month(char a, char b, char c)
{
        setMonth(a, b, c);
}

void Month::setMonth(char a, char b, char c)
{
        setMonth(translateStr(a, b, c));
}

int Month::translateStr(char a, char b, char c)
{
        std::string str = "";
        str += a;
        str += b;
        str += c;

        for (int i = 1; i <= 12; i++)
        {
                if (str == translateNum(i))
                {
                        return i;
                }
        }

        return 0; //error,查詢不到
}

std::string Month::translateNum(int num)
{
        static std::string table =
        {
                "Jan", //1月
                "Feb", //2月
                "Mar", //3月
                "Apr", //4月
                "May", //5月
                "Jun", //6月
                "Jul", //7月
                "Aug", //8月
                "Sep", //9月
                "Oct", //10月
                "Nov", //11月
                "Dec"  //12月
        };

        if (num <= 0 || num > 12)
        {
                return "";
        }
        else
        {
                return table;
        }
}



會出錯是不是因為傳遞的是自動變數,而不能使用reference的關係?還是說……?


...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><div></div>

tryit244178 發表於 2019-3-24 06:13 PM

因為nextMonth回傳的型別是Month,但=右側要放入的卻是Month&。所以無法轉換

vincent-vincent 發表於 2019-4-3 09:38 AM

int 跟 int* 是不一樣的東西,這個可以理解嗎?
那Month跟Month&也就是不一樣的東西啦,一個是值一個是位址。
你這段像是想要寫成 車子A = 車子B,但卻寫成了 車子A = 停著車子B的車庫

z1090128 發表於 2019-4-14 01:39 PM

就是指標概念吧,傳送位址資訊,和資料資訊的差異

hi625096 發表於 2019-4-25 11:58 PM

本帖最後由 hi625096 於 2019-4-26 12:02 AM 編輯

簡單做一個概述,在C++ 中&配合變數宣告或是函數參數時是參考(Reference)的意思,
若&與一個變數單獨使用則與C語言的&等價就是取地址。
Ex: int &rnum = num; 參考
      int *pnum = # 取地址
------------------------------------------------------------------------------------------
參考可以視為為這個變數取一個小名,當你操作這個參考時等價於操作該變數本身,所以sizeof()該參考的大小會與該變數相同,所以在C++中使用參考當函數參數時不需要傳入地址,直接傳入該變數即可達到與call by address的效用,
在C++中這個方法叫做 call by reference。
------------------------------------------------------------------------------------------
參考有分為左值(left value)與右值(right value)參考,以下做簡單敘述:
左值: 擁有記憶體實體,簡單說該變數正在記憶體中(參考記憶體中的值)
右值: 沒有記憶體實體,該變數目前在暫存器中(參考暫存器的值)
參考的本質是指標,當一個參考未參考任何變數時該參考的大小就是指標的大小,在C++中參考可以降低程序的複雜度簡化程式碼
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><br><br><br><br><br><div></div>
頁: [1]