C++之继承
-
继承
-
在原有类的基础上,进行更具体,更详细的定义;
-
交通工具
-
火车、汽车(面包车,轿车,卡车)、轮船、飞机、mobike
-
-
-
类的继承是新的类从已有的类中得到已有的特性;
-
性质:
-
1、传递性(火车 汽车 都具有交通工具的共同特征);
-
2、不对称性(不是所有的汽车都叫五菱宏光)
-
-
过程:
-
1、从原有类拿到“所有内容”(除了基类的构造、析构 和 静态成员,还有有元);
-
2、改造从原有类拿到的东西;(同名函数的隐藏)
-
3、创造自己的新东西。
-
-
继承和派生:
-
从新的类获取已有类的内容的过程 称为继承;从已有类创造出新的类的过程 称为派生。
-
-
原有的类: 父类=基类
-
新的类: 子类=派生类
-
语法:
-
class 基类
{};
class 派生类:继承方式 基类1,继承方式 基类2
{};
-
单继承和多继承:
-
一个派生类,可以同时有多个基类(父类),即多继承;
-
一个派生类,只有一个直接基类,即单继承
-
-
间接基类和直接基类
-
在类族中,直接参与派生出某类的基类称为直接基类,基类的基类,甚至更高的基类称为间接基类
-
-
派生类继承父类后,从父类继承的成员在派生类中如何访问?
父类成员属性
|
public(类内外皆可访问)
|
protexted(类内可以,内外不能)
|
private(只能在类内部访问)
|
子类继承方式pubic(公有继承)
|
public:类内类外都可以访问
|
protected:需要通过成员函数
|
无法直接访问
|
protected(保护继承)
|
protected:只能是在内部访问
|
protected:只能是在内部访问
|
无法直接访问
|
private(私有继承)
|
private:私有只能通过函数调用
|
private:私有只能通过函数调用
|
无法直接访问
|
-
表格的说明:
-
-
公有继承、基类的三个成员无法访问
-
-
保护继承、基类私有成员无法直接访问
-
私有继承
-
和保护继承一样
-
-
继承方式:
-
继承方式决定了子类如何从基类继承成员
-
public
-
protected
-
private
-
对于基类来说:public 类内外皆可访问
-
protected 类内可以,派生类内可以访问
-
private 只能在类内部访问,不能再外部访问
-
-
对于派生类来说:公有继承 意味着基类的公有成员和保护成员的访问属性在派生类中不变,而基类的私有成员在派生类中不可直接访问。
-
保护继承 意味着基类的公有成员和保护成员的访问属性在派生类中都以保护的身份出现,而基类的私有成员在派生类中不可直接访问
-
私有继承 意味着基类的公有成员和保护成员的访问属性在派生类中都已私有的身份出现,而基类的私有成员在派生类中不可直接访问
-
-
-
-
继承的重要说明:
-
1、子类拥有所有的成员变量和成员方法(除了析构,构造,静态,有元)
-
2、子类就是一种特殊的父类
-
3、子类对象可以当做父类对象使用
-
4、子类可以拥有父类没有的成员和方法
-
-
继承的复杂例子:
-
-
-
构造顺序是 父类 cons 、子类cons 、子类des、父类des。
-
-
-
类型兼容性原则:(见有道云C++)指在需要基类对象的任何地方,都可以使用公有派生类(前提)对象来代替,通过公有派生,派生类得到了基类中除了构造和析构的所有成员,此外派生类继承而来的成员属性不变,这样公有派生类实际上就具备了基类所有功能,凡是基类能解决的问题,公有派生类都可以解决。(子类是一个特殊的父类)
-
子类对象可以当做父类对象使用
-
子类对象可以直接赋值给父类对象
-
子类对象可以直接初始化父类对象或引用(但是是交给父类了)
-
父类指针可以直接指向子类对象
-
-
int main()
{
B b;A a;C c;
B b1 = c;//子类对象可以当做父类对象使用
b1.fun();//结果"B fun with no argument"
//--------------------------------------------------------------------
b = c;//子类对象可以直接赋值给父类
b.fun();//结果是"B fun with no argument"
//---------------------------------------------------------------------
A &pa = c;//子类对象可以直接初始化父类对象的引用
pa.fun();//结果是"A fun with no argument"
//---------------------------------------------------------------------
A *pb = &c;//父类指针可以直接指向子类对象
pb->fun();//结果是"Afun with no argument"
return 0;
}
-
继承、派生子类
-
-
所有的参数要比函数形参低一辈
-
-
如果子类拥有和父类同名的函数,该子类将隐藏父类的同名函数
-
-
继承的构造和析构
class A{int x, int y;};A--x,y //A是爷爷类
class B{int m, int n;};B--A(x,y)--m,n //B是爸爸类 他继承A的成员x,y,然后还有自己的成员m,n
class C{int z;};C--B(A(x,y)---m,n)---z //C是儿子类 他继承B的所有成员,即B中A的(x,y)和B自己的m,n,然后还有自己的成员z
-
子类对象构造时,需要调用父类的构造函数 对子类继承而来的成员(“父类成员”)进行初始化。
-
子类对象析构时,需要调用父类的析构函数 对继承而来的成员进行析构。
-
-
构造顺序:在子类构造时,会首先调用父类的构造函数,来初始化继承来的父类成员,然后按照 “构造函数初始化列表”中的指定方式来初始化子类自己的新增成员,最后执行子类构造函数的函数体。
-
语法格式
子类的构造函数:
子类名::子类名(参数表):父类名1(父类1的初始化参数列表),父类名n(父类n的初始化参数列表),子类成员对象名1(成员对象1的初始化参数列表),成员对象名n(成员对象n的初始化参数列表)
{
函数体;
}
-
子类构造函数的实现
-
-
父类带参 和不带参 组合 派生子类 的构造函数 (不带参的父类隐藏不写)
-
-
注:如果基类是带参构造,派生类就必须在编写派生类构造函数时,主动声明基类的构造函数。
-
继承的组合例子(拷贝构造)
-
Object类
-
-
-
继承自Object的Parent类
-
-
继承自Parent的Child类
-
-
主函数
-
-
在继承中遇见同名函数
-
子类和父类拥有相同名称的函数,子类对象默认调用的是子类的同名函数,如果要调用继承而来的符的同名函数 需要显式加上父类作用域区分符。
-
无论同名函数的参数个数和类型是否一致,
-
-
-
-
static在继承中的作用
-
如果基类有个static静态成员(不被继承),该成员被所有基类对象共享,如果基类派生出子类,该成员依旧可以被子类对象共享,但是需要遵循类的访问控制机制。
-
-
-
-
基类无法访问子类的静态成员 但是子类可以访问基类的静态成员(不对称性)
-
-
-
模板的继承
-
继承只能发生在子类和父类之间,也就是说继承只能发生在类之间,因此,模板想要继承,需要先具体化模板类,C++编译器需要知道具体的数据类型,才能知道该怎么分类内存。
-
(test1)
-
-
模板类继承模板类(test2)
-
-