C++中基类与派生类的复制控制

来源:互联网 发布:mac pc 区别 编辑:程序博客网 时间:2024/05/01 22:42

本博文的创作思路源自《C++ Primer(4th Ed )》的习题15.20

运行环境Ubuntu 、g++

#include <iostream>#include <string>using namespace std;class Item_base{public:Item_base(const string &book = "Item_base", double SalesPrice = 1):isbn(book), price(SalesPrice) {cout << "构造函数Item_base(const string&, double )" << endl;}virtual double NetPrice(size_t n) const//不同购买量不同计价方式{return n * price;}Item_base(const Item_base& it)//复制构造函数{ //isbn = it.isbn;//price = it.price;cout << " 复制构造函数Item_base(const Item_base& it) " << endl; }Item_base& operator =(const Item_base& right){isbn = right.isbn;price = right.price;cout << "赋值函数Item_base::operator =(Item_base& left, Item_base& right)" << endl;return *this;// return *left;}virtual ~Item_base() //{ cout << "析构函数~Item_base" << endl; }void print(){ cout << "isbn:" <<isbn << "    price:" << price << endl;}private:string isbn;protected:double price;};//Item_base& Item_base::operator =(Item_base& left, Item_base& right)//{//left.isbn = right.isbn;//left.price = right.price;//cout << "Item_base::operator =(Item_base& left, Item_base& right)" << endl;//return *this;// return *left;//}class Bulk_item : public Item_base{public:Bulk_item(const string &book ="bulk_item", double SalesPrice = 2,size_t qty = 0, double dis = 0.0) :Item_base(book, SalesPrice), min_qty(qty), discount(dis){ cout << "构造函数Bulk_item(const string &book, double, size_t, double)" << endl; }double NetPrice(size_t cnt) const{if(cnt < min_qty)return cnt * price;elsereturn cnt * (1 - discount) * price;}Bulk_item(const Bulk_item & Bulk){cout << "复制构造函数Bulk_item(const Bulk_item &)" << endl; }Bulk_item& operator=(Bulk_item& right){if(this != &right)Item_base::operator =(right);min_qty = right.min_qty;discount = right.discount;cout << "赋值函数Bulk_item& oprator=(Bulk_item& right)" << endl;return *this;}virtual ~Bulk_item()//{cout << "析构函数~Bulk_item()" << endl; }private:size_t min_qty;double discount;};void func1(Item_base obj){obj.print();}void func2(Item_base& obj){obj.print();}Item_base func3(){Item_base obj;return obj;}int main(){Item_base item; //调用构造函数,并在最后析构cout << "1" << endl<<endl;func1(item);//调用复制构造函数,目的是将形参item_base对象创建为实参item_base对象的副本//函数执行完毕后调用item_base的析构函数,撤销形参对象,cout << "3" << endl<<endl;func2(item);//不调用复制构造函数传递实参,因为形参为Item_base对像的引用cout << "4" << endl<<endl;item = func3(); //调用构造函数,创建Item_base对象//调用赋值函数//在函数接受时调用析构函数撤销刚刚创建的对象cout << "5" << endl<<endl;Item_base *p = new Item_base; //调用构造函数创建动态Item_base对象cout << "6" << endl<<endl;delete p; //调用析构函数撤销刚刚动态创建的Item_base对象cout << "7" << endl<<endl;Bulk_item bulk;//调用bulk_item构造函数创建bulk_item对象,由于是派生类对象//在调用这个构造函数时会先调用item_base构造函数//并在最后析构cout << "8" << endl<<endl;func1(bulk);//bulk_item会隐式转换为item_base//调用item_base的复制构造函数,目的是将形参item_base对象创建为实参item_base对象的副本。cout << "9" << endl << endl;func2(bulk);  //bulk_item会隐式转换为item_basecout << "10" << endl << endl;//Item_base item;//bulk = func3();//调用失败,因为item_base不会隐式转换为bulk_item//cout << "11" << endl << endl;Bulk_item *q = new Bulk_item;  //动态创建,调用的函数与创建Bulk_item对象相同,不再赘述cout << "12" << endl << endl;delete q;//调用~bulk_item与~item_base撤销动态创建的对象cout << "13" << endl << endl;}
程序在何时执行哪个函数已在注释行说的很清楚了。这里只是有点要说名:

在调用func1(item)时会出现乱码:

如图:


原因是因为它调用的是合成版本的复制构造函数,如果将item_base复制构造函数里的两个注释行取消掉,将不会出现这种情况

isbn = it.isbn;price = it.price;
如图:


而对于func2()无论注不注释上面的两行对程序的结果的都没有影响。是因为func2()的形参为引用,它不会保存为实参的副本。

从bulk = func3()的错误中我们可以发现,派生类可以隐式转换为基类,而反之则不行。