进入正题之前我们来说一说关系
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在派生类重新定义基类方法
Son s;
Father f;
s.f();//Son.f()
f.f();//Father.f()
2使用虚方法
<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纯虚函数可一再派生类中不定义