第16课 - 继承中的构造与析构

1. 赋值兼容性原则

(1)      子类对象可以当作父类对象使用。

(2)      子类对象可以直接赋值给父类对象。

(3)      子类对象可以直接初始化父类对象。

(4)      父类指针可以直接指向子类对象。

(5)      父类引用可以直接引用子类对象。

子类就是特殊的父类

#include <cstdlib>

#include <iostream>

using namespace std;

class Parent

{

protected:

const char* name;

public:

Parent()

{

name = "Parent";

}

void print()

{

cout<<"Name: "<<name<<endl;

}

};

class Child : public Parent

{

protected:

int i;

public:

Child(int i)

{

this->name = "Child";

this->i = i;

}

};

int main(int argc, char *argv[])

{

Child child(1000);

Parent parent = child;  //用子类对象赋值父类对象

Parent* pp = &child;   //父类指针指向子类对象,因为子类就是特殊的父类

Parent& rp = child;    //父类的引用,引用子类的内容

parent.print();   //打印父类内容

pp->print();     //打印父类指针

rp.print();       //打印父类引用

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Name:Child

Name:Child

Name:Child

2. 继承对象模型

类在C++编译器的内部可以理解为结构体,子类是由父类成员叠加子类新成员得到的。

问题:如何初始化父类成员?父类与子类的构造函数有什么关系?

3. 继承与构造

在子类对象构造的时候需要调用父类构造函数对其继承得来的成员进行初始化。

4. 继承与析构

在子类对象析构的时候需要调用父类析构函数对其继承得来的成员进行清理。

C++特有继承的构造与析构的关系,使得当拿来一段程序的时候,我们可以直接建立我们使用的子类的构造与析构函数,即使我们不了解父类的构造与析构函数,我们也能正常的写程序。

程序:

#include <cstdlib>

#include <iostream>

using namespace std;

class Parent

{

public:

Parent()

{

cout<<"Parent()"<<endl;

}

~Parent()

{

cout<<"~Parent()"<<endl;

}

};

class Child : public Parent

{

public:

Child()

{

cout<<"Child()"<<endl;

}

~Child()

{

cout<<"~Child()"<<endl;

}

};

void run()

{

Child child;

}

int main(int argc, char *argv[])

{

run();

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Parent<>

Child<>

~Child<>

~Parent<>

5. 继承的构造与析构

(1)      子类对象在创建时会首先调用父类的构造函数。

(2)      父类构造函数执行结束后,执行子类的构造函数。

(3)      当父类的构造函数有参数时,需要在子类的初始化列表中显示调用。

(4)      析构函数调用的先后顺序与构造函数相反。

程序:

#include <cstdlib>

#include <iostream>

using namespace std;

class Parent

{

public:

Parent(const char* s)   //父类的构造函数是有参数的

{

cout<<"Parent()"<<" "<<s<<endl;

}

~Parent()

{

cout<<"~Parent()"<<endl;

}

};

class Child : public Parent

{

public:

Child() : Parent("Parameter from Child!") /*在初始化子类的时候,先初始化父类的构造函数 */

{

cout<<"Child()"<<endl;

}

~Child()

{

cout<<"~Child()"<<endl;

}

};

void run()

{

Child child;

}

int main(int argc, char *argv[])

{

run();

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Parent<> Parameter from Child!

Child<>

~Child<>

~Parent<>

6. 继承与组合的混搭

类中的成员变量可以是其它类的对象。

问题:

如果一个类继承自父类并且有其它的对象作为成员,那么构造函数如何调用?

口诀:先父母,后客人,再自己。

程序:

#include <cstdlib>

#include <iostream>

using namespace std;

class Object

{

public:

Object(const char* s)

{

cout<<"Object()"<<" "<<s<<endl;

}

};

class Parent : public Object

{

public:

Parent(const char* s) : Object(s)

{

cout<<"Parent()"<<" "<<s<<endl;

}

};

class Child : public Parent

{

protected:

Object o1;

Object o2;

public:

Child() : o2("o2"), o1("o1"), Parent("Parameter from Child!")

/*后面这排叫做初始化列表,用于父类继承的初始化*/

{

cout<<"Child()"<<endl;

}

};

void run()

{

Child child;

}

int main(int argc, char *argv[])

{

run();

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Object<> Parameter from Child!

Parent<> Parameter from Child!

Object<> o1

Parent<>o2

Child<>

分析:

我们要“先父母”,打印Parameter from Child!,但是Parent还是有上面的继承的,所以要先打印Object<> Parameter from Child!  后打印Parent<> Parameter from Child!

初始化列表里面的顺序是没有用的,我们要看程序中的初始化顺序。

7. 同名成员变量

思考:当子类中定义的成员变量与父类中的成员变量同名时会发生什么?

当子类成员变量与父类成员变量同名时,子类依然从父类继承同名成员。在子类中通过作用域分别符::进行同名成员区分,同名成员存储在内存中的不同位置。

程序:

#include <cstdlib>

#include <iostream>

using namespace std;

class Parent

{

protected:

int i;

int f;

};

class Child : public Parent

{

protected:

int i;

void f()

{

cout<<"Parent::i = "<<Parent::i<<endl;

cout<<"Child::i = "<<Child::i<<endl;

cout<<"Parent::f = "<<Parent::f<<endl;

}

public:

Child(int i, int j)

{

Parent::i = i;

Child::i = j;

Parent::f = i + j;

f();

}

};

void run()

{

Child child(1, 3);

}

int main(int argc, char *argv[])

{

run();

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Parent::i = 1

Child::i = 3

Parent::f = 4

类有点像命名空间,命名空间的同名变量的区分,是根据::来区分的。我们这里面用的区分方法一样。

小结:

(1)      子类对象可以当作父类对象使用。

(2)      子类对象在创建时需要调用父类构造函数进行初始化。

(3)      子类对象在销毁时需要调用父类析构函数进行清理。

(4)      先执行父类构造函数(执行到父类,别忘了父类的父类),再执行成员构造函数。

(5)      在继承中的析构顺序与构造顺序对称相反。

(6)      同名成员通过作用域分辨符进行区分。

转载于:https://www.cnblogs.com/free-1122/p/11336220.html

C++--第16课 - 继承中的构造与析构相关推荐

  1. c++继承中的构造和析构

    c++继承中的构造和析构 类型兼容性原则 类型兼容规则中所指的替代包括以下情况: 继承中的对象模型 继承中构造和析构 继承中的构造析构调用原则 继承与组合混搭情况下,构造和析构调用原则 继承中的同名成 ...

  2. C++继承机制(二)——继承中的构造和析构顺序、继承同名成员的处理方式

    目录: C++继承机制(一)--基本语法.三种继承方式.继承哪些数据 C++继承机制(二)--继承中的构造和析构顺序.继承同名成员的处理方式 C++继承机制(三)--多继承.菱形继承.虚继承原理 本篇 ...

  3. C++继承中的构造与析构

    文章目录 1 C++继承中的构造 1.1 子类对象初始化父类成员的方式 1.2 子类对象的构造 2 C++继承中的析构 2.1 子类对象的析构 1 C++继承中的构造 1.1 子类对象初始化父类成员的 ...

  4. 【C++深度剖析教程25】继承中的构造与析构

    今天来学习C++中继承的构造与析构,有兴趣一起学习的加qq:1126137994 1.问题 如何初始化父类成员?父类构造函数与子类构造函数有什么关系? 子类对象是如何构造的? 子类中可以定义构造函数 ...

  5. C++_类和对象_C++继承_继承中的构造和析构顺序---C++语言工作笔记064

    然后我们再去看c++中的构造和析构函数的执行的顺序. . 直接用案例说明,可以看到,上面呢,我们写个Base类,然后 写这个类的构造方法. 然后我们在Base类中写上构造方法,和析构方法. 然后我们再 ...

  6. (转)剖析Delphi中的构造和析构

    剖析Delphi中的构造和析构 1 Delphi中的对象模型: 2 1.1 对象名表示什么? 2 1.2 对象存储在哪里? 2 1.3 对象中存储了什么?它们是如何存储的? 3 2 构造函数与创建对象 ...

  7. 继承中构造和析构顺序

    1.子类继承父类后,当创建子类对象,也会调用父类的构造函数 2.继承中先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反 #include<iostream> using name ...

  8. c/c++入门教程 - 2.4.6 继承、公共继承、保护继承、私有继承、virtual虚继承(概念、语法、方式、构造和析构顺序、同名成员处理、继承同名静态成员处理、多继承语法、菱形继承、钻石继承)

    目录 4.6 继承 4.6.1 继承的基本语法 4.6.2 继承方式 4.6.3 继承中的对象模型 4.6.4 继承中构造和析构顺序 4.6.5 继承同名成员处理方式 4.6.6 继承同名静态成员处理 ...

  9. c++中的继承--2(继承中的析构函数和构造函数,继承中同名成员,继承中静态成员)

    继承中的构造函数和析构函数 继承中的构造和析构顺序 子类创建对象时,先调用父类的构造,然后调用自身构造 析构顺序与构造顺序相反 子类不会继承父类的构造函数和析构函数 如果父类中没有合适默认构造,那么子 ...

  10. c++继承-----继承中构造函数写法

    父类中的属性: 调用父类的构造函数初始化 成员函数的方式初始化 子类中的构造函数: 必须要调用父类构造函数 必须采用初始化参数列表的方式 子类想构造无参对象,父类必须要写无参构造函数(隐式调用构造函数 ...

最新文章

  1. ASP.NET 2.0 中的新增安全功能
  2. 牛逼啊!一个可以随时随地写Python代码的神器
  3. UA MATH564 概率论IV 次序统计量例题2
  4. Zuul(SpringCloud学习笔记一)
  5. uclinux下实现多线程[转]
  6. 使用GlassFish 3.1.2.2和Primefaces 3.4的JDBC领域和基于表单的身份验证
  7. 【转】WPF调用图片路径,或资源图片
  8. 企业实战(Jenkins+GitLab+SonarQube)_08_jenkins安装和第一个Java项目构建
  9. 你的网站首页完成最重要的使命了吗?
  10. npm install socket.io 提示缺少VCBuild.exe
  11. 一道笔试题的解法和联想
  12. java 相等测试与继承
  13. jqGrid设置三级表头和表头合并
  14. HITB CTF 2018 gundam 做题笔记
  15. JavaScript实现单击切换图片
  16. matlab无法用mcc,使用matlab的mcc时为什么会出现fopen错误?
  17. Qt之时间轴样式汇总
  18. 淘宝网店应该怎么样去做好宝贝SEO优化?
  19. NFT Insider #49:YGG学员总量突破20000名,《南华早报》在The Sandbox中构建香港天星码头
  20. 区块链教程(2)——P2P交易原理

热门文章

  1. Flink+Hudi 构架湖仓一体化解决方案
  2. Deploy Apache Flink Natively on YARN/Kubernetes
  3. 用python爬取图片和搞笑段子
  4. php 代码格式化命令,go fmt命令——格式化代码文件
  5. mysql修改视图语句alter_MySQL修改视图(ALTER VIEW)
  6. java麻麻_知了堂教你不怂密密麻麻的Java代码
  7. mysql修改密码1054_Mysql修改密码异常处理(ERROR 1054)
  8. java 锁的重入_Java 的可重入锁和不可重入锁
  9. Django结合Bootstrap分页显示mysql中的值
  10. 使用oracle执行txt语句,oracle常用SQL语句.txt