文章目录
继承
什么是继承
面向对象编程的主要目的之一是代码复用。
传统的C函数库通过预定义、预编译的函数(如strlen()和rand()),提供了可重用性。
C++类提供了更高层次的重用性—类继承:它能够从已有的类(基类或父类)派生出新的类(即派生类或子类)。派生类可以继承基类中除了构造和析构外的所有东西(注意:友元关系也是不能继承的,举例就像父亲的朋友而不是儿子的朋友)。
- 普通/静态成员变量
- 普通/静态成员方法
派生类
派生类的内存布局
查看内存布局:cl main.cpp /d1reportSingleClassLayoutDerive
派生类的构造和析构
先构造的后析构
class Base
{
public:
Base(int a):ma(a)
{
cout<<"Bash::Bash()"<<endl;
}
void show()
{
cout<<"Bash::show()"<<endl;
cout<<ma<<endl;
}
void show(int rhs)
{
cout<<"Bash::show(int)"<<endl;
int sum=ma+rhs;
cout<<sum<<endl;
}
~Base()
{
cout<<"Bash::~Bash()"<<endl;
}
private:
int ma;
};
class Derive:public Base
{
public:
//Bash(b) 指明基类部分的构造方式:调用带有一个整型参数的构造函数
Derive(int b):mb(b),Base(b)
{
cout<<"Derive::Derive()"<<endl;
}
void show()
{
cout<<"Derive::show()"<<endl;
cout<<mb<<endl;
}
~Derive()
{
cout<<"Derive::~Derive()"<<endl;
}
private:
int mb;
};
int main()
{
Derive d(20);
return 0;
}
在派生类构造函数中如果不给Base构造函数赋默认值 则:
error C2512: “Base”: 没有合适的默认构造函数可用 当生成一个派生类对象的时候: 首先开辟内存 :8个字节 包括基类和派生类 int ma; int mb; 调用构造函数:对整个内存进行初始化 而基类的构造函数、析构函数是不会被继承的 初始化时,对mb初始化,对ma也是要初始化的 对于基类中的东西,不应该单单认为是一个内存块,而应该认为是一个对象 针对基类中的东西,也要调用基类的构造函数进行初始化。 系统在派生类构造前,得先调用构造对于基类部分初始化,而对于基类编译器指挥调用默认的构造函数。 而此时基类中没有默认的构造函数,所以就会报错!
派生类生成:
- 开辟内存
- 调用构造
- 基类的构造
- 派生类的构造
派生类销毁:
- 调用析构
- 派生类的析构
- 基类的析构
- 释放内存
继承方式
公有继承-public
以公有继承方式继承:
- 基类中的公有数据:在派生类中也是公有的
- 如果在派生类类外可以访问 ,则继承的数据就在public下存放
- 如果不能访问,两种情况: 基类中保护的数据以公有的继承方式继承过来 是在私有 或者 保护下
- 结果证明:是公有的,派生类和外部都可以访问
- 基类中的保护数据:
- 结果证明:派生类可以访问,外部不能访问,则就表示在保护下
- 基类中的私有数据:
- 结果证明:不允许访问,私有数据只允许在本类类中访问
私有继承-private
- 基类中的共有数据
- 结果证明:私有,派生类中可以访问,外部不可以
- 基类中的保护数据
- 结果证明:私有,派生类中可以访问,外部不可以
- 基类中的私有数据
- 不允许访问,私有数据只允许在本类类中访问
保护继承-protected
- 基类中的共有数据
- 如果在派生类类外不能访问 ,则继承的数据就在私有 或 保护下
- 如果此派生类又派生了第三个类(即孙子类)如果在孙子类中可以访问此数据,则说明数据在派生类的保护限定符下
- 结果证明:在保护访问限定符下,本类和子类类中可以访问,即派生类和孙子类可以访问
- 基类中的保护数据
- 如果在派生类类外不能访问 ,则继承的数据就在私有 或 保护下
- 如果此派生类又派生了第三个类(即孙子类)如果在孙子类中可以访问此数据,则说明数据在派生类的保护限定符下
- 结果证明:在保护访问限定符下,本类类和子类类可以访问,即派生类和孙子类可以访问
- 基类中的私有数据
- 不允许访问,私有数据只允许在本类类中访问
同名函数
重载(overload)
即重定义(函数重载) 同名 不同参 不同作用域
覆盖(override)
即重写 同名 同参 不同作用域 并且是继承层次下
举例:基类与派生类中都是虚函数(不管派生类中函数名前有没有virtual关键字,它都是虚函数),则派生类的虚函数会覆盖基类的虚函数。 在继承关系下,析构也满足同名覆盖的关系。
如果在基类中的虚函数,但在派生类中没有显式实现,那么不会发生覆盖,只有在派生类中显式实现的虚函数,才会发生同名覆盖关系。
隐藏(overhide)
同名 不同作用域 并且是继承关系
举例:
(1)如果基类与子类中存在同名函数,不同参,此时无论基类中的函数是否是虚函数,都会被隐藏。
(2)如果基类不是虚函数,派生类中存在与基类同名同参的函数,就会隐藏基类的函数。
- 如果能使用派生类对象加作用域可以调用基类中的同名同参函数,就说明是隐藏的。
基类指针和派生类的相互指向或引用
基类的指针或引用 可以 指向或者引用派生类对象
派生类的指针或引用 不可以 指向或引用基类对象
- 什么类型的指针就只能访问什么部分
- 基类可以指向或引用派生类,是因为派生类继承了基类,所以它可以操作派生类中的基类部分。
- 派生类指针可访问派生类部分 但他指向本质是一个基类的对象,而基类中并没有派生类的数据,一旦访问就会出错