1. 程式人生 > 實用技巧 >C++面向物件入門(二十四)過載賦值運算子

C++面向物件入門(二十四)過載賦值運算子

為什麼要過載賦值運算子?

在使用者定義類後, 編譯器會預設提供無參構造(空實現), 析構(空實現), 拷貝構造(值拷貝), 過載賦值運算子(值賦值)

但是若類成員屬性為指標變數時, 編譯器提供的過載賦值運算子只會簡單的把指標變數的值賦值, 而不會申請一份新的記憶體空間, 將指標指向的變數賦值給這片記憶體空間,

當我們在析構中釋放記憶體時, 就會出現一段的記憶體被重複釋放的情況, 從而導致程式執行出錯. 故需要自己給出過載賦值運算子函式

示例程式碼:

#include <iostream>
#include <string>


using namespace std;
/** * recipe n.祕訣;處方;食譜; * 為什麼要過載賦值運算子? *在使用者定義類後, 編譯器會預設提供無參構造(空實現), 析構(空實現), 拷貝構造(值拷貝), 過載賦值運算子(值賦值) *但是若類成員屬性為指標變數時, 編譯器提供的過載賦值運算子只會簡單的把指標變數的值賦值, 而不會申請一份新的記憶體空間, 將指標指向的變數賦值給這片記憶體空間, *當我們在析構中釋放記憶體時, 就會出現一段的記憶體被重複釋放的情況, 從而導致程式執行出錯. 故需要自己給出過載賦值運算子函式 * 語法: * 類名 &operator=(const 類名 &變數名) * { * 函式體 * } * 注意事項: * 1, 對於這種含有指標型別的成員變數的類, 其建構函式中應該都有申請記憶體空間的語法 * 因此不需要再過載賦值運算子函式中再申請記憶體 * 2, 函式返回值型別應該引用型別, 返回值為呼叫物件的的引用(使用*this指標返回)
*/ const int MAXSIZE = 100; double abs(double a) { if(a < 0) return -a; return a; } class Item { string name; double price; int quantity; public: Item() { } Item(const string &name, double price, int quantity) : name(name), price(price), quantity(quantity) {} };
struct Goods { string name; double price; string getInfo() { return "name: " + name + ", price: " + to_string(price); } }; ostream &operator<<(ostream &cout, const Goods &goods); class Store { friend ostream &operator<<(ostream &cout, const Store &store); private: double balance; Item *itemList; Goods *menu; int goodsQuantity; public: const string name = "MINI STORE"; Store() : balance(0),goodsQuantity(0) { this->itemList = new Item[MAXSIZE]; this->menu = new Goods[MAXSIZE]; } Store(double balance, Item *itemList, Goods *menu, int goodsQuantity) : balance(balance), goodsQuantity(goodsQuantity) { this->itemList = new Item[MAXSIZE]; this->menu = new Goods[MAXSIZE]; for (int i = 0; i < goodsQuantity; ++i) { this->itemList[i] = itemList[i]; this->menu[i] = menu[i]; } } ~Store() { cout << "Close the Store" << endl; } Store &operator=(const Store &store) { balance = store.balance; goodsQuantity = store.goodsQuantity; for (int i = 0; i < goodsQuantity; ++i) { this->itemList[i] = store.itemList[i]; this->menu[i] = (store.menu)[i]; } return *this; } }; ostream &operator<<(ostream &cout, const Goods &goods) { cout << "name:" << goods.name << ", price:" << goods.price; return cout; } ostream &operator<<(ostream &cout, const Store &store) { cout << "name:" << store.name << endl; cout << "MENU:" << endl; for (int i = 0; i < store.goodsQuantity; ++i) { if(abs(store.menu[i].price-0) > 1e-6) cout << store.menu[i] << endl; } cout << "balance:" << store.balance << endl; return cout; } void test1() { Item itemList[] = {Item("apple", 2.5, 10), Item("watermelon", 1.2, 100), Item("grape", 10, 15)}; Goods menu[] = {Goods{"apple", 2.5}, Goods{"watermelon", 1.2}, Goods{"grape", 10}}; Store store = {100, itemList, menu, 3}; Store s2; cout << "Before assign, the object s2 is :" << endl; cout << s2; s2 = store; cout << "After assign, the object s2 is :" << endl; cout << s2; } int main() { test1(); system("pause"); return 0; }