一、基本概念

1、类的继承,是新的类从已有类那里得到已有的特性。或从已有类产生新类的过程就是类的派生。原有的类称为基类或父类,产生的新类称为派生类或子类。
2、派生类的声明:
class 派生类名:继承方式 基类名1, 继承方式 基类名2,...,继承方式 基类名n
{
    派生类成员声明;
};
3、一个派生类可以同时有多个基类,这种情况称为多重继承,派生类只有一个基类,称为单继承。直接派生,间接派生。
4、继承方式规定了如何访问基类继承的成员。继承方式有public, private, protected。如果不显示给出继承方式,默认为private继承。继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。
5、派生类继承基类中除构造和析构函数以外的所有成员。
6、派生类生成:
   吸收基类成员(除构造析构函数以外的所有成员);
   改造基类成员(根据继承方式调整基类成员的访问,函数在子类中的覆盖,以及虚函数在子类中的覆盖);
   添加新的成员;
7、公有继承
当类的继承方式为公有继承时,基类的公有和保护成员的访问属性在派生类中不变,而基类的私有成员不可访问。即基类的公有成员和保护成员被继承到派生类中仍作为派生类的公有成员和保护成员。派生类的其他成员可以直接访问它们。无论派生类的成员还是派生类的对象都无法访问基类的私有成员。
8、私有继承
当类的继承方式为私有继承时,基类中的公有成员和保护成员都以私有成员身份出现在派生类中,而基类的私有成员在派生类中不可访问。基类的公有成员和保护成员被继承后作为派生类的私有成员,派生类的其他成员可以直接访问它们,但是在类外部通过派生类的对象无法访问。无论是派生类的成员还是通过派生类的对象,都无法访问从基类继承的私有成员。通过多次私有继承后,对于基类的成员都会成为不可访问。因此私有继承比较少用。
9、保护继承
保护继承中,基类的公有成员和私有成员都以保护成员的身份出现在派生类中,而基类的私有成员不可访问。派生类的其他成员可以直接访问从基类继承来的公有和保护成员,但是类外部通过派生类的对象无法访问它们,无论派生类的成员还是派生类的对象,都无法访问基类的私有成员。
二、派生类的构造函数和析构函数
1、派生类中由基类继承而来的成员的初始化工作还是由基类的构造函数完成,然后派生类中新增的成员在派生类的构造函数中初始化。
2、派生类构造函数的语法:
派生类名::派生类名(参数总表):基类名1(参数表1),基类名(参数名2)....基类名n(参数名n),内嵌子对象1(参数表1),内嵌子对象2(参数表2)....内嵌子对象n(参数表n)
{
派生类新增成员的初始化语句;
}
注:构造函数的初始化顺序并不以上面的顺序进行,而是根据声明的顺序初始化。
3、如果基类中没有不带参数的构造函数,那么在派生类的构造函数中必须调用基类构造函数,以初始化基类成员。
4、派生类构造函数执行的次序:
调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左到右);
调用内嵌成员对象的构造函数,调用顺序按照它们在类中声明的顺序;
派生类的构造函数体中的内容。
例子:
#include <iostream>
#include <time.h>
using namespace std;class B1
{
public:B1(int i){cout<<"constructing B1 "<<i<<endl;}
};class B2
{
public:B2(int j){cout<<"constructing B2 "<<j<<endl;}
};class B3
{
public:B3(){cout<<"constructing B3"<<endl;}
};class C: public B2, public B1, public B3
{
public:C(int a, int b, int c, int d):B1(a), memberB2(d), memberB1(c),B2(b){}
private:B1 memberB1;B2 memberB2;B3 memberB3;
};int main()
{ C obj(1,2,3,4);return 0;
}
输出结果为:
constructing B2 2
constructing B1 1
constructing B3
constructing B1 3
constructing B2 4
constructing B3
5、析构函数
派生类的析构函数的功能是在该对象消亡之前进行一些必要的清理工作,析构函数没有类型,也没有参数。析构函数的执行顺序与构造函数相反。
例子:
#include <iostream>
#include <time.h>
using namespace std;class B1
{
public:B1(int i){cout<<"constructing B1 "<<i<<endl;}~B1(){cout<<"destructing B1"<<endl;}
};class B2
{
public:B2(int j){cout<<"constructing B2 "<<j<<endl;}~B2(){cout<<"destructing B2"<<endl;}
};class B3
{
public:B3(){cout<<"constructing B3"<<endl;}~B3(){cout<<"destructing B3"<<endl;}
};class C: public B2, public B1, public B3
{
public:C(int a, int b, int c, int d):B1(a), memberB2(d), memberB1(c),B2(b){}
private:B1 memberB1;B2 memberB2;B3 memberB3;
};int main()
{ C obj(1,2,3,4);return 0;
}
输出结果为:
constructing B2 2
constructing B1 1
constructing B3
constructing B1 3
constructing B2 4
constructing B3
destructing B3
destructing B2
destructing B1
destructing B3
destructing B1
destructing B2
三、派生类成员的标识和访问
1、派生类成员属性划分为四种:
不可访问的成员;私有成员;保护成员;公有成员;
2、作用域分辨
形式为:基类名::成员名;基类名::成员名(参数表);
如果某派生类的多个基类拥有同名的成员,同时,派生类又新增这样的同名成员,在这种情况下,派生类成员将覆盖所有基类的同名成员。这就需要这样的调用方式才能调用基类的同名成员。
例子:多继承同名 
#include <iostream>
#include <time.h>
using namespace std;class B1
{
public:int nV;void fun(){cout<<"member of B1 "<<nV<<endl;}
};class B2
{
public:int nV;void fun(){cout<<"member of B2 "<<nV<<endl;}
};class D1: public B1, public B2
{
public:int nV;void fun(){cout<<"member of D1 "<<nV<<endl;}
};int main()
{ D1 d1;d1.nV = 1;d1.fun();d1.B1::nV = 2;d1.B1::fun();d1.B2::nV = 3;d1.B2::fun();return 0;
}

输出结果为:
member of D1 1
member of B1 2
member of B2 3
以上通过作用域分辨符,解决了访问基类中被屏蔽的同名成员。
3、如果某个派生类的部分或全部直接基类是从另一个共同的基类派生而来,在这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,因此派生类中也就会产生同名现象,对这种类型的同名成员也要使用作用域分辨符来唯一标识,而且必须用直接基类进行限定。
例子:
#include <iostream>
#include <time.h>
using namespace std;class B0
{
public:int nV;void fun(){cout<<"member of B0 "<<nV<<endl;}
};class B1:public B0
{
public:int nV1;
};class B2:public B0
{
public:int nV2;
};class D1:public B1, public B2
{
public:int nVd;void fund(){cout<<"member of D1"<<endl;}
};int main()
{ D1 d1;d1.B1::nV = 2;d1.B1::fun();d1.B2::nV = 3;d1.B2::fun();return 0;
}

输出结果为:
member of B0 2
member of B0 3
在这种情况下,派生类对象在内存中就同时拥有成员nV及fun的两份拷贝。但是很多情况下,我们只需要这样一个这样的数据拷贝,同一成员的多份拷贝增加了内存的开销。可以通过虚函数来解决这个问题。
4、虚基类
为了解决前面提到的多重拷贝的问题,可以将共同基类设置为虚基类,这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数也只有一个映射。
虚基类的声明是在派生类的声明过程,其语法形式为:
class 派生类名::virtual 继承方式 基类名;
例子:
#include <iostream>
#include <time.h>
using namespace std;class B0
{
public:int nV;void fun(){cout<<"member of B0 "<<nV<<endl;}
};class B1:virtual public B0
{
public:int nV1;
};class B2:virtual public B0
{
public:int nV2;
};class D1:public B1, public B2
{
public:int nVd;void fund(){cout<<"member of D1"<<endl;}
};int main()
{ D1 d1;d1.nV = 2;d1.fun();return 0;
}

输出结果为:
member of B0 2
5、虚基类及其派生类的构造函数
一般而言,派生类只对其直接基类的构造函数传递参数,但是在虚基类中,不管是直接或间接虚基类的所有派生类,都必须在构造函数的成员初始化列表中列出对虚基类的初始化。
例子:
#include <iostream>
#include <time.h>
using namespace std;class B0
{
public:B0(int n){nV = n;}int nV;void fun(){cout<<"member of B0 "<<nV<<endl;}
};class B1:virtual public B0
{
public:B1(int a):B0(a)   {}int nV1;
};class B2:virtual public B0
{
public:B2(int a):B0(a){}int nV2;
};class D1:public B1, public B2
{
public:D1(int a):B0(a), B1(a), B2(a){}int nVd;void fund(){cout<<"member of D1"<<endl;}
};int main()
{ D1 d1(1);d1.nV = 2;d1.fun();return 0;
}

以上例子看上去B0的构造函数好像被调用了三次,但是实际上只有D1类中的D1(int a):B0(a), B1(a), B2(a)
才是真正的调用了B0构造函数。
四、赋值兼容规则
1、赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。
2、赋值兼容规则中所指的替代包括:
派生类的对象可以赋值给基类对象;
派生类的对象可以初始化基类的引用;
派生类对象的地址可以赋给指向基类的指针。
在替代之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员。
例子:
#include <iostream>
#include <time.h>
using namespace std;class B0
{
public:void display(){cout<<"B0::display()"<<endl;}
};class B1:public B0
{
public:void display(){cout<<"B1::display()"<<endl;}
};class B2:public B0
{
public:void display(){cout<<"B2::display()"<<endl;}
};void fun(B0 *ptr)
{ptr->display();
}int main()
{ B0 b0;B1 b1;B2 b2;fun(&b0);b0 = b1;fun(&b0);b0 = b2;fun(&b0);return 0;
}

输出结果为:

B0::display()

B0::display()

B0::display()

通过这种赋值兼容后,每次调用的同名函数都是基类的同名函数,如果想调用派生类的,则需要使用虚函数。

c++ 类的继承与派生相关推荐

  1. 类的继承和派生java_类的继承和派生

    一.类的继承和派生定义. 继承:保持已有类的特性而构造新类的过程称为继承. 派生:在已有类的基础上新增自己的特性而产生新类的过程称为派生. 被继承的已有类称为基类. 派生出的新类称为派生类. 二.继承 ...

  2. 模块的封装之C语言类的继承和派生

    [交流][微知识]模块的封装(二):C语言的继承和派生 在模块的封装(一):C语言的封装中,我们介绍了如何使用C语言的结构体来实现一个类的封装,并通过掩码结构体的方式实 现了类成员的保护.这一部分,我 ...

  3. C++类的继承与派生

    文章目录 一.继承 二.基类和派生类 三.继承方式 六.多继承 七.应用经验 八.课后作业 九.版权声明 一.继承 继承是面向对象程序设计中最重要的一个概念.继承允许我们根据一个类来定义另一个类,达到 ...

  4. C++语言类的继承与派生介绍和示例

    继承 继承是面向对象程序设计中最重要的一个概念.继承允许我们根据一个类来定义另一个类,达到了代码功能重用效果. 当创建一个类时,如果待创建的类与另一个类存在某些共同特征,程序员不需要全部重新编写成员变 ...

  5. 实验四 类和对象;类的继承和派生;多态性; 接口;构造器应用

    实验四 类和对象:类的继承和派生:多态性: 接口:构造器应用 一.实验目的 1. 掌握类与对象的关系: 2. 掌握类的定义: 3. 掌握对象的声明及使用: 4. 掌握构造方法的概念及调用时机: 5. ...

  6. 【C++进阶知识】C++类的继承和派生

    目录 C++进阶知识系列文章 C++类的继承和派生 基本语法 访问修饰符 构造函数和析构函数 覆盖父类的方法 虚函数和纯虚函数 示例代码 参考资料 C++进阶知识系列文章 C++类的继承和派生 在面向 ...

  7. python 钻石继承_python3--object类,继承与派生,super方法,钻石继承问题

    python3--object类,继承与派生,super方法,钻石继承问题 发布时间:2018-04-13 20:38:05编辑:Run阅读(1914) 昨天内容复习 组合:什么有什么的关系(例:老师 ...

  8. c 自定义实现string类 clear_CC++语言15|类的继承和派生实现代码重用、扩充

    在C++中,继承是一个对象自动获取其父对象的所有属性和行为的过程.通过继承,您可以重用,扩展或修改在其他类中定义的属性和行为.通过继承,可以实现函数重写以及多态. 在C++中,继承另一个类的成员的类称 ...

  9. PTA 6-1 类的继承和派生

    本题实现类的额继承和派生.已经给出相关的数据结构和类的声明,要求实现类的相关函数,为保证比较的结果,所有的数据均以int类型(除了PI取3.14外),程序运行时,输入一个点p的坐标x和y,接着是圆的中 ...

最新文章

  1. 37_04_awk入门进阶
  2. SQL Server 重置SA密码语句
  3. 敲山震虎?继MongoDB之后,AWS又对Elasticsearch下手了
  4. 由浅入深:自己动手开发模板引擎——置换型模板引擎(一)
  5. 手动为 SAP Spartacus 添加 SSR 支持的步骤
  6. Workaround for Search for my account in MyAppointment
  7. 4G DTU使用教程
  8. mysql控制台教程视频教程_mysql 控制台操作
  9. q7goodies事例_Java 8 Friday Goodies:本地交易范围
  10. mysql删除外键_MySQL删除外键定义的方法
  11. Gartner:2020年数据与分析领域的十大技术趋势
  12. C语言 - 数组作为参数传递给函数(按值传递和按引用传递)
  13. JavaScript—从数组的indexOf方法深入——Object的Property机制。
  14. 百度离线地图JS API V3.0
  15. tolua unity 报错_Unity3D热更新技术点——ToLua(上)
  16. 1_绪论 分布式机器学习
  17. 干货!图像集分类大杀器--混合黎曼度量学习
  18. 【微信小程序】企业付款接口
  19. 统计学习三要素个人理解
  20. IATF16949认证辅导,IATF16949涵盖汽车行业特定要求和辅导工具以及再整个供应链中减少变差和浪费的质量管理体系

热门文章

  1. 在VS2012中安装使用cppcheck
  2. mysql Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nona
  3. Django:ORM关系字段
  4. .NET错误:未找到类型或命名空间名称
  5. Java WEB之Servlet学习之路(一)一个最简单的Servlet应用
  6. 软件测试作业4:测试要素
  7. JPEG原理分析及JPEG解码器的调试
  8. 【数据结构与算法】之深入解析“二叉树的中序遍历”的求解思路与算法示例
  9. 2018年第九届蓝桥杯 - 省赛 - C/C++大学B组 - F.递增三元组
  10. Java中集合(七)Collections 一个操作集合的工具类