C++ Primer学习笔记 — 复制控制与继承

本文介绍派生类的复制构造函数、赋值操作符及析构函数的实现方法,强调了如何正确地使用基类的复制构造函数初始化派生类对象,并通过实例演示了整个过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

只包含类类型或内置类型数据成员、不含指针的类一般可以使用合成操作,复制、赋值或撤销这样的成员不需要特殊控制。具有指针成员的类一般需要定义自己的复制控制来管理这些成员

1.定义派生类复制构造函数

注解:如果派生类显式定义自己的复制构造函数或赋值操作符,则该定义将完全覆盖默认定义。被继承类的复制构造函数和赋值操作符负责对基类成分以及类自己的成员进行复制或赋值。

如果派生类定义了自己的复制构造函数,该复制构造函数一般应显式使用基类复制构造函数初始化对象的基类部分:

class Base { /* ... */ };
     class Derived: public Base {
     public:
         // Base::Base(const Base&) not invoked automatically
         Derived(const Derived& d):
              Base(d) /* other member initialization */ { /*... */ }
             //此处显示使用基类复制构造函数初始化对象的基类部分,若省略基类初始化函数,结果是运行Base的默认构造函数初始化对象的基类部分
     };
2.派生类赋值操作符

赋值操作符通常与复制构造函数类似:如果派生类定义了自己的赋值操作符,则该操作符必须对基类部分进行显式赋值

// Base::operator=(const Base&) not invoked automatically
     Derived &Derived::operator=(const Derived &rhs)
     {
        if (this != &rhs) {
            Base::operator=(rhs); // assigns the base part
            // do whatever needed to clean up the old value in the derived part
            // assign the members from the derived
        }
        return *this;
     }

3.派生类析构函数

析构函数的工作与复制构造函数和赋值操作符不同:派生类析构函数不负责撤销基类对象的成员。编译器总是显式调用派生类对象基类部分的析构函数。每个析构函数只负责清除自己的成员:

class Derived: public Base {
     public:
         // Base::~Base invoked automatically
         ~Derived()    { /* do what it takes to clean up derived members */ }
      };
对象的撤销顺序与构造顺序相反:首先运行派生析构函数,然后按继承层次依次向上调用各基类析构函数

4.例子

说了这么多,我们还是看一个例子吧

#include <iostream>
#include <string>

using namespace std;

class Item_base
{
	public:
		Item_base(const string &book = "", double sales_price = 0.0) : isbn(book), price(sales_price)
	    {
	       cout << "Item_base(const string&, double)" << endl;
		}
        
        string book() const
		{
	       return isbn;
		}

        virtual double net_price(size_t cnt)
		{
		   return cnt * price;
		}

		Item_base(const Item_base &rhs) : isbn(rhs.isbn), price(rhs.price)
		{
		   cout << "Item_base(const Item_base&)" << endl;
		}

		Item_base& operator = (const Item_base &rhs)
		{
		     isbn = rhs.isbn;
			 price = rhs.price;
			 cout << "Item_base& operator = (const Item_base&)" << endl;
			 return *this;
		}

		virtual ~Item_base()
		{
		   cout << "~Item_base()" << endl;
		}
	private:
		string isbn;
	protected:
		double price;
};



class Bulk_item : public Item_base
{
	public:
		Bulk_item(const string &book = "", double sales_price = 0.0, size_t qty = 0, double disc_rate = 0.0)
		: Item_base(book, sales_price), min_qty(qty), discount(disc_rate)
		{
		    cout << "Bulk_item(const string&, double, size_t, double)" << endl;
		}
        
		double net_price(size_t cnt)
		{
		   if(cnt > min_qty){
				return cnt * price * (1 - discount);
		   }else
                return cnt * price;  
		}

		Bulk_item(const Bulk_item &rhs) : Item_base(rhs), min_qty(rhs.min_qty), discount(rhs,discount)
		{
		    cout << "Bulk_item(const Bulk_item &rhs)" << endl;
		}

        Bulk_item& operator = (const Bulk_item &rhs)
		{
		    if(this != &rhs){
				Item_base::operator = (rhs);
				min_qty = rhs.min_qty;
				discount = rhs.discount;
			}
			cout << "Bulk_item& operator = (const Bulk_item&)" << endl;
			return *this;
		}

		virtual ~Bulk_item()
		{
		   cout << "~Bulk_item()" << endl;
		}

	private:
		size_t min_qty;
	    double discount;

};

void func1(Item_base obj)
{

}


void func2(Item_base &obj)
{

}

Item_base func3()
{
    Item_base obj;
    return obj;
}

int main()
{
   Item_base iobj;

   func1(iobj);

   func2(iobj);

   iobj = func3();

   Item_base *p = new Item_base;

   delete p;

   Bulk_item bobj;

   func1(bobj);

   func2(bobj);

   Bulk_item *q = new Bulk_item;

   delete q;

   return 0;
}
运行结果如下,并解释如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值