c++类继承

进入正题之前我们来说一说关系

has-a 午餐可以有苹果,但是苹果不是午餐,所以苹果是午餐的一部分,我叫has-a

is-like-a 人们通常说律师是鲨鱼,但是律师不是鲨鱼,只是律师像鲨鱼

is-implemented-as-a (作为什么来实现)可以用数组来实现栈,但是从array派生stack不合适,因为栈不是数组

uses-a 计算机可以使用打印机

is-a 苹果和香蕉都是水果,

而我们说的共有继承就是is-a 关系

派生一个类

<pre class="cpp" name="code">class Father{
int father_var
};//基类

class Son:public Father{
int son_var
}//子类Son,public公有基类,称为共有派工
 

上面代码完成了一下任务

1派生类型存储了基类的数据成员

2派生类对象可以使用基类的方法

那我们怎么写派生类呢?

1派生类需要有自己的构造函数

2派生类可以根据需要添加额外的数据成员和成员函数

派生类构造函数

首先派生类不能直接访问基类的私有成员,而必需通过基类方法进行访问,具体说,如果想用派生类初始化基类的私有数据,派生类构造函数必须使用基类构造函数

成员初始化列表

创建派生对象时程序首先创建的是基类对象,从概念上说,这意味着派生类构造函数应在进入构造函数之前创建基类,c++使用成员初始化列表完成这种工作

Son::Son():Father(){};//其中:Father()是成员初始化列表调用Father()构造函数

如果不写成员成员初始化列表,编译器也会使用默认的成员初始化列表;

成员初始化列表 除了可以初始化基类的构造函数,还可以初始化成员,但是名字就要变成成员名了,不能写类名了

Son::Son():Father(){},father_var(233);//中间用逗号分开

注意

1派生类首先创建基类对象

2派生类构造函数应通过成员初始化列表将基类信息传递给基类构造函数

3派生类构造函数应初始化新增的成员变量

4析构函数和构造函数调用相反,先派生类再到基类

使用派生类

派生类和基类之间的特殊关系

1派生类可以使用基类的方法,前提是方法不是私有的
2基类指针(引用也可以)可以在不进行显示类型转换的情况下指向派生对象,但是这样只能使用基类的方法,派生类的方法就不能使用了
3共有继承是is-a关系

多态共有继承

希望方法在基类和派生类的行为不同-这种行为就是多种形态有两种机制实现多态共有继承

1在派生类重新定义基类方法

当我们根据派生类还是基类定义了不同函数之后,编译器会根据对象类型调用函数;
Son s;
Father f;
s.f();//Son.f()
f.f();//Father.f()

2使用虚方法

加上关键字virtual之后,方法将会变成虚方法

<pre class="cpp" name="code">//如果f()是不同函,而virtual_f()是虚函数
Son s;
Father f;
Father& Reference_s=s;
Father& Reference_f=f;
Reference_s.f();//Father.f()
Reference_f.f();//Father.f()

Reference_s.virtual_f();//Son.f();
Reference_f.virtual_f();//Father.f();

 

如果方法是通过指针和引用调用的,那么不同函数会根据引用类型或指针类型来调用函数,而virtual函数引用和指针指向的类型调用函数

注意

虚析构函数就是为了防止通过指针和引用来调用析构函数穿线的问题

静态联编写和动态联编

将原代码函数解释为执行特定的函数代码块称为数名联编

1编译过程中进行联编称为静态联编

对于非虚函数是根据指针和引用类型判断调用的,而指针和引用类型是可以在编译之前就确定的所以 编译器使用静态联编绑定函数名和代码块

2运行过程中进行联编为动态联编


对于虚函数 ,他是根据指针和引用指向类型判断调用的,所以编译器只能在运行时进行动态联编

上面的问题解决完了 有出现了下面的问题

1为什么有两种联编

2既然动态联编怎么好,为什么不把他设置成默认

3动态联编是如何工作的

解答

1效率和感念

由于动态联编是是在运行时实现的,所以必须有额外的开销来完成之间是,所以效率没有静态联编高

2因外效率问题所以静态联编是默认的

3c++规定了虚函数的行为,但是没有规定其实现。所以我们只能介绍。

c++为每一个对象提供了一个指针,这个指针指向了存储着虚函数地址的数组。这样就可以进行动态联编了

总结

1如果派生类重定义函数就应该使用虚函数,否则不用

2提供虚函数

3重定义将会隐藏函数

class Father{
public :void f(int );
};
class Son:public Father{
public :void f();
};

Son::f()将会覆盖Father::f(int),所以你使用Son::f(5);将会报错根,所以注意一下两点

①重定义函数原型应相同,但是函数返回类型可以改变

②如果基类声明被重载了,应该在派生类定义所有基类版本


访问权限:protected

在类的外部和private一样,唯一不同的就是基类中protected声明的变量在派生类中是被看着public的

抽象类

如果类中有至少一个纯虚函数来那么这个类就是抽象类

void f()=0;//纯虚函数

1抽象类是不能创建对象的

2纯虚函数可一再派生类中不定义


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值