C++ Primer 5th笔记(chap 15 OOP)构造函数和拷贝控制
1. 虛析構函數
基類通常應該定義一個虛析構函數。
class Quote { public:// virtual destructor needed if a base pointer pointing to a// derived object is deletedvirtual ~Quote() = default; // dynamic binding for the destructor };如果基類的析構函數不是虛函數,則delete一個指向派生類對象的基類指針會產生未定義的結果。
Quote *itemP = new Quote; // same static and dynamic type delete itemP; // destructor for Quote called itemP = new Bulk_quote; // static and dynamic types differ delete itemP; // destructor for Bulk_quote called虛析構函數會阻止編譯器為類合成移動操作(有析構就有拷貝構造和拷貝賦值,那么編譯器就不會合成移到操作了)
2. 合成拷貝控制與繼承
基類或派生類的合成拷貝控制成員的行為和其他合成的構造函數、賦值運算符或析構函數類似:對類本身的成員依次進行初始化、賦值或銷毀的操作。如果成員是一個對象,還使用對象的初始化、賦值或銷毀的操作。
基類沒有移到操作那么它的派生類也沒有。
2.1 派生類中的刪除拷貝控制與基類的關系
● 如果基類中的默認構造函數、拷貝構造函數、拷貝賦值運算符或析構函數是被刪除的或者不可訪問的函數,則派生類中對應的成員也會是被刪除的。因為編譯器不能使用基類成員來執行派生類對象中基類部分的構造、賦值或銷毀操作。
● 如果基類的析構函數是被刪除的或者不可訪問的,則派生類中合成的默認和拷貝構造函數也會是被刪除的。因為編譯器無法銷毀派生類對象中的基類部分。
● 編譯器不會合成一個被刪除的移動操作。當我們使用=default請求一個移動操作時,如果基類中對應的操作是被刪除的或者不可訪問的,則派生類中的操作也會是被刪除的。因為派生類對象中的基類部分不能移動。同樣,如果基類的析構函數是被刪除的或者不可訪問的,則派生類的移動構造函數也會是被刪除的。
在實際編程中,如果基類沒有默認、拷貝或移動構造函數,則一般情況下派生類也不會定義相應的操作。
2.2. 移到操作和繼承
因為基類缺少移動操作會阻止編譯器為派生類合成自己的移動操作,所以當我們確實需要執行移動操作時,應該首先在基類中進行定義。
class Quote{public:Quote() = default;Quote(const string& s, double sales_price) :bookNo(s), price(sales_price) {}Quote(const Quote&);//拷貝構造函數Quote& operator=(const Quote&);//拷貝賦值運算符Quote(Quote&&);//移動構造函數Quote& operator=(Quote&&);//移動賦值運算string isbn() const;virtual double net_price(size_t n) const;//虛函數virtual void debug() const;virtual ~Quote() {}//對析構函數進行動態綁定private:string bookNo;protected:double price = 0.0;};ostream& print_total(ostream& os, const Quote& item, size_t n){double ret = item.net_price(n);os << "ISBN:" << item.isbn()<< " #sold: " << n << " total due: " << ret << endl;item.debug();return os;}string Quote::isbn() const{return bookNo;}double Quote::net_price(size_t n) const{return n * price;}void Quote::debug() const{cout << "i am quote:" << bookNo << " " << price << endl;}Quote::Quote(const Quote& q){cout << "hello i am 拷貝構造函數Quote" << endl;bookNo = q.bookNo;price = q.price;}Quote& Quote::operator=(const Quote& q){cout << "hello i am 拷貝賦值運算符Quote" << endl;if (this != &q){bookNo = q.bookNo;price = q.price;}return *this;}Quote::Quote(Quote&& q){cout << "hello i am 移動構造函數Quote" << endl;bookNo = std::move(q.bookNo);price = std::move(q.price);q.bookNo = "";q.price = 0;}Quote& Quote::operator=(Quote&& q){cout << "hello i am 移動賦值運算符Quote" << endl;if (this != &q){bookNo = std::move(q.bookNo);price = std::move(q.price);q.bookNo = "";q.price = 0;}return *this;}void test() {Quote test("cuinan", 100);Quote test1(test);Quote test2;test2 = test;Quote test3(std::move(test));test2 = std::move(test);}輸出結果:
hello i am 拷貝構造函數Quote
hello i am 拷貝賦值運算符Quote
hello i am 移動構造函數Quote
hello i am 移動賦值運算符Quote
【引用】
[1] 代碼oopTest.h
總結
以上是生活随笔為你收集整理的C++ Primer 5th笔记(chap 15 OOP)构造函数和拷贝控制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Primer 5th笔记(cha
- 下一篇: C++ Primer 5th笔记(cha