多載指定運算子
在前一章,我們學會了如何多載比較運算子,一種非常常用的運算子種類。
今天我們要來多載指定運算子 =
,英文叫做 assignment operator,也叫做 copy assignment operator。
多載這個運算子讓我們可以客製化指定物件為某一個值的這個過程。
讓我們繼續看下去吧!
多載 =
因為這不是我們第一次多載運算子,因此,在這章我們就直接來看該如何多載 =
運算子吧!
這裡我們和之前一樣,使用 Dollars
作為我們的範例。
class Dollars { private: int m_dollars; public: Dollars() {}; Dollars(int dollars) : m_dollars{ dollars } {} Dollars& operator=(const Dollars& d); int getDollars() const { return m_dollars; } }; Dollars& Dollars::operator=(const Dollars& d) { m_dollars = d.getDollars(); return *this; } int main() { Dollars d1{10}; Dollars d2; d2 = d1; std::cout << d2.getDollars() << std::endl; return 0; }
執行後,我們會看到這樣的輸出:
10
如果有好好讀完前面幾章的人,那你應該是非常清楚這樣的程式碼在做什麼~
這裡我就不介紹了,我們要來談一個更為重要的觀念!
指定運算子 v.s. 複製建構子
還不熟悉什麼是複製建構子的人,可以去看看這章 複製建構子 Copy Constructor。
這兩個東西做的事情非常像,因此常常有很多初學者搞不清楚這兩者的區別。
這兩個東西其實都是在賦予物件某個值,但賦予的手段有些許不同。
- 在複製建構子中,物件是先被創造,然後才被賦予值。
- 在指定運算子中,沒有物件被創造,被賦予值的物件是本來就存在的
我們來看這個稍微複雜一點的例子:
class Dollars { private: int m_dollars; // 美元金額 std::string m_currency; // 貨幣單位 public: // 預設建構子 Dollars() : m_dollars(0), m_currency("USD") { std::cout << "呼叫預設建構子" << std::endl; } // 參數化建構子 Dollars(int dollars, const std::string& currency) : m_dollars(dollars), m_currency(currency) {} // 複製建構子 Dollars(const Dollars& other) : m_dollars(other.m_dollars), m_currency(other.m_currency) { std::cout << "呼叫複製建構子" << std::endl; } // 複製指定運算子 Dollars& operator=(const Dollars& other) { std::cout << "呼叫複製指派運算子" << std::endl; if (this != &other) { m_dollars = other.m_dollars; m_currency = other.m_currency; } return *this; } friend std::ostream& operator<<(std::ostream& os, const Dollars& dollars) { os << "金額:" << dollars.m_dollars << " " << dollars.m_currency; return os; } }; int main() { // 使用參數化建構子創建實例 Dollars dollar1(100, "USD"); std::cout << dollar1 << std::endl; // 使用複製建構子從 dollar1 創建 dollar2 Dollars dollar2 = dollar1; std::cout << dollar2 << std::endl; // 使用複製指定運算子將 dollar2 的值複製到 dollar3 Dollars dollar3; dollar3 = dollar2; std::cout << dollar3 << std::endl; return 0; }
執行程式碼後,我們可以看到這樣的輸出:
金額:100 USD 呼叫複製建構子 金額:100 USD 呼叫預設建構子 呼叫複製指派運算子 金額:100 USD
可以看到,在將 dollar1
複製給 dollar2
時,我們是使用複製建構子 Copy Constructor。
複製建構子「先」創造了 dollar2
,「再」將 dollar1
的值複製過去。
而在將 dollar2
複製給 dollar3
時,我們是使用複製指定運算子 Copy Assignment Operator。
這是因為物件 dollar3
原本就已經存在了,指定運算子只是將 dollar2
的值複製過去而已。
隱藏的指定運算子
和複製建構子一樣,如果我們不多載指定運算子,C++ 編譯器會暗中幫我們生成一個。
也就是說,如果刪掉這段:
// 複製指定運算子 Dollars& operator=(const Dollars& other) { std::cout << "呼叫複製指派運算子" << std::endl; if (this != &other) { m_dollars = other.m_dollars; m_currency = other.m_currency; } return *this; }
程式碼依然可以執行!
總結
這篇我們又學到了一個多載運算子的實際應用啦!
如何多載指定運算子我相信如果你們有看前幾章的話那肯定不難,重要的是要能分清楚 copy assignment operator 和 copy constructor 這兩個概念,以及程式碼什麼時候呼叫哪個!
這對於想要深刻理解 C++ 的人來說非常重要,因為這會涉及到記憶體的處理。
那這篇就到這裡啦!有學到東西的話歡迎留五星評價喔!