本博文的创作思路源自《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;
else
return 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_base
cout << "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()的错误中我们可以发现,派生类可以隐式转换为基类,而反之则不行。