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;
}

 

posted @ 2020-08-29 10:08  DNoSay  阅读(235)  评论(0编辑  收藏  举报