C++之所以不同于C,是因为多了三大特性:封装、继承、多态。
本文章着重介绍:继承与多态
一.继承
(1)继承的基本介绍
class A{};
class B: public A{};
^ ^ ^
派生类 继承方式 基类
而派生类(子类)中的成员访问变化方式满足这个公式:
Min(成员基类的访问权限,继承方式)
而派生类中对于基类的protected访问权限可以访问,但是对于private访问权限不可以访问!
(2)基类与派生类对象的赋值转换
1.对象赋值
基类对象不可以赋值给派生类对象,派生类对象可以赋值给基类对象!
就像切片一样把属于Person那部分直接赋值给它
2.指针赋值
对ptr->_name 进行操作的同时也是对s._name操作
(3)继承中的作用域
1.基类与派生类都有自己独立的作用域
2.重定义(隐藏):基类与派生类若有同名成员(函数,成员变量),派生类将基类中的同名成员屏蔽,构成隐藏,若想访问,可以指定作用域(基类::基类成员)来进行访问。
(4)继承中的构造与析构
构造:先对基类构造,再对派生类构造(可以手动,因为初始化列表是按声明顺序进行定义,而基类对象是第一个声明的)
析构:先对派生类析构,再对基类析构(自动调用,不可以手动,不然可能会出现问题)
(5)多继承
但是对于多继承可能造成数据冗余,如以下这种情况
有两份植物的继承,既数据冗余,又有二义性
为了防止这种情况引出了 virtual 这个关键字
在分叉点的所有指向的对象前加入virtual
class B: virtual public A{};
class C:virtual public A{};
(6)继承与组合
继承是 class A:public B{};
而组合是 class A
{
B b;
}组合 继承 继承与组合
相比下组合更优,因为更加符合高内聚,低耦合的特性。
二 .多态
不同对象做同一行为的不同表现,如叫:(猫是喵喵),(狗是汪汪)
也可以叫做函数的重写(要求函数名,参数,返回相同)
对于要重写的函数,基类函数前必须加virtual,派生类可以不加,但是最好写
总结:
(1)对于继承的析构函数
因为多态的运用(C++中将析构函数统一命名为destructor),所以对于delete 基类指针
满足多态条件,指向谁调用谁,所以调用了基类的析构没有析构派生类,所以基类析构函数最好必须加上virtual。
(2)协变
基类(基类与派生类虚函数返回值类型不同)
当基类函数返回基类对象指针或引用,派生类函数返回派生类对象指针或者引用时,称为协变
(3)补充
对于基类函数的同名的函数声明
就相当于函数由基类的声明,加派生类的定义构成。
(4)虚函数表
我们知道对于构成多态的函数来说,调用指向位置的类所对应的函数。
但是编译器是怎么知道该如何调用的呢?
这里我们就引入了虚函数表,对于每个有虚函数的类中,都有一个虚函数表,而虚函数表需要占用空间,并且虚函数中指向对应函数的调用地址。
编译器就是根据虚函数表中地址来在运行时进行调用。