(十五)面向对象程序设计(Part3)

copy from(https://blog.csdn.net/billcyj/article/details/78888074)

15.7 构造函数和拷贝控制

创建、拷贝、移动、赋值和销毁

15.7.1 虚析构函数

继承体系中的析构函数应该定义为虚函数。
以前说过,定义了析构函数就要定义拷贝和赋值,但这里基类的析构函数是例外。

为什么?

保证可以动态分配继承体系中的对象。且delete时能执行对应的析构函数。
若指针指向继承体系中的某个类型,则可能出现指针的静态类型和被删除对象的动态类型不符合:
如:delete一个Quote*类型指针,该指针指向Bulk_quote类型对象。那应该执行Bulk_quote的析构函数。

virtual ~Quote()=default;

15.7.2 合成拷贝控制与继承

  • 派生类中定义为删除的拷贝控制与基类的关系
class B
{
public:
    B(); //默认构造函数声明
    B(const B&) = delete; //定义为删除的拷贝构造函数
    //既然定义了拷贝构造函数,就不会合成移动操作了
};
class D : public B
{
    //没有声明任何东西,只是单纯继承了B
};
D d; //正确:D的合成默认构造函数调用B的默认构造函数,自己反正也没成员
D d2(d); //错误:因为B的拷贝构造函数是delete的,所以D的也是delete,无法被调用
 
  • 移动操作与继承

移动操作:基类多有虚析构函数,所以不会合成移动操作,如果确实需要,应首先在基类中显式定义,此时要同时显式定义拷贝操作:

class Quote
{
public:
    Quote() = default; //强行合成默认构造函数

    Quote(const Quote&) = default; //拷贝构造函数
    Quote(Quote&&) = default; //移动构造函数
    Quote& operator=(const Quote&) = default; //拷贝赋值
    Quote& operator=(Quote&&) = default; //移动赋值

    virtual ~Quote() = default; //虚析构函数
};

如此,Quote的派生类也会自动获得合成的移动操作。

15.7.3 派生类的拷贝控制成员

派生类的拷贝和移动构造函数在拷贝和移动自有成员的同时,也要拷贝和移动基类部分,赋值运算符也类似。
而析构函数只负责销毁派生类自己分配的资源 基类部分自动销毁

  • 定义派生类的拷贝或移动构造函数
class Base
{

};
class D : public Base
{
//我们要拷贝或移动基类部分,就必须在派生类的构造函数初始值列表中显式调用
public:
    D(const D& d) : Base(d) {} //调用基类的拷贝构造函数来拷贝基类部分
    //这儿比较特殊的是Base(d)会去匹配Base的拷贝构造函数,虽然人家其实接受B类型

    D(D&& d) : Base(std::move(d)){}
};
  • 派生类赋值运算符

也就是拷贝赋值和移动赋值。

D &D::operator=(const D &rhs)
{
    Base::operator=(rhs); //显式地为基类部分赋值:(合成的或自定义的)基类的拷贝赋值运算符将释
    //放掉左侧对象的基类部分的旧值,然后利用rhs为其赋一个新值
    //接下来为派生类自己的部分赋值(省略)
    return *this;
}

  • 派生类析构函数

对象销毁的顺序与创建顺序相反:派生类析构函数先执行,然后执行基类的析构函数。
也就是,对直接基类部分拷贝后,再拷贝类本身的成员;销毁本身后再销毁基类,基类部分会自动销毁。

禁止在构造或析构函数中调用虚函数
假设我们在基类的构造函数中调用派生类的某个函数去访问其成员,这会派生类对象还没构建完成,怎么能访问呢?于是,C++禁止了这种行为。

15.7.4 继承的构造函数

1.派生类类不能继承基类的默认构造函数、拷贝构造函数、移动构造函数;
2.但派生类能够重用其基类自定义的构造函数;
3.派生类中的基类成员调用基类的构造函数初始化,派生类中的其他成员将被默认初始化

class Bulk_quote : public Disc_quote
{
public:
    using Disc_quote::Disc_quote; //使用using继承Disc_quote的构造函数
};

把using放到构造函数上时,using声明语句将令编译器产生代码,而且,编译器会生成一个与基类对应的派生类构造函数,针对上面的例子生成的派生类构造函数如下

Bulk_quote(const string& book, double price, size_t qty, double disc) : Disc_quote(book, price, qty, disc) {}

  • 继承的构造函数的特点

1.构造函数的using声明不会改变该构造函数的访问级别
2.如果基类的构造函数是explicit或constexpr的,则继承的构造函数也是
3.当一个基类构造函数含有默认实参,派生类将获得多个继承的构造函数,其中每个构造函数分别忽略掉一个含有默认实参的形参
另外,如果派生类自己又定义了一个和基类构造函数具有相同参数列表的构造函数,那么基类的这个构造函数不会被继承,就用派生类自己定义的就好了,覆盖了

15.8 容器与继承

我们不能把具有继承关系的多种类型的对象直接存放在容器中:

vector<Quote> basket;
basket.push_back(Bulk_quote("a", 50, 10, 0.25));

basket的元素是Quote对象,因此当我们向其中添加Bulk_quote对象时,属于派生类的部分会被忽略

容器中应放置指针(最好是智能指针)而非对象

vector<shared_ptr<Quote>> basket;
basket.push_back(make_shared<Quote>("a", 50));
basket.push_back(make_shared<Quote>("b", 50, 10, 0.25));
cout << basket.back()->net_price(15) << endl; //打印折扣后的价格,这回派生类对象是完整的

基类的指针 则指向对象的动态类型可能是基类也可能是派生类

派生类应反映与基类的Is A关系,公有派生类的对象应该可以用在任何需要基类对象的地方;类之间Has A则是包含成员的意思。
对于C++面向对象的编程来说,并不是直接用对象,用的是指针和引用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容