一.静态联编
1.联编是指一个程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系; 就是把函数调用与函 数的程序代码连接(联系)在一起的过程。
2.联编分为两大类
1)静态联编
调用速度快,效率高,但缺乏灵活性。
C++为了兼容C语言仍然是编译型的,采用静态联编。
2)动态联编
运行效率低,但增强了程序灵活性。
为了实现多态性,利用虚函数机制,可部分地采用动态联编。
二.类指针的关系
基类指针和派生类指针与基类对象和派生类对象4种可能匹配:
1.直接用基类指针引用基类对象
2.直接用派生类指针引用派生类对象
3.用基类指针引用一个派生类对象
4.用派生类指针引用一个基类对象
(一)基类指针引用派生类对象
A * p ; // 指向类型 A 的对象的指针
A A_obj ; // 类型 A 的对象
B B_obj ; // 类型 B 的对象
p = & A_obj ;// p 指向类型 A 的对象
p = & B_obj ;// p 指向类型 B 的对象,它是 A 的派生类
(二)派生类指针引用基类对象
1.不能将一个声明为指向派生类对象的指针指向其基类的对象。
2.派生类指针只有经过强制类型转换之后,才能引用基类对象
三.虚函数与动态联编
(一)实现动态联编方式的前提
1.先要声明虚函数
2.类之间满足赋值兼容规则:派生类公有继承基类
3.通过指针与引用来调用虚函数。
(二)虚函数
- 冠以关键字 virtual 的成员函数称为虚函数
- 实现运行时多态的关键首先是要说明虚函数
- 必须用基类指针调用派生类的不同实现版本
虚函数的重载特性
在派生类中重载基类的虚函数要求函数名、返回类型、参数个数、参数类型和顺序完全相同。
注意:
1.构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数。
2.析构函数可以是虚的。虚析构函数用于指引 delete 运算符正确析构动态对象。
3.虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态函数。
4.构造函数、内联成员函数、静态成员函数不能是虚函数。(虚函数不能以内联的方式进行处理)
(三)虚析构函数
1.构造函数不能是虚函数。
2.析构函数可以是虚的。虚析构函数用于指引 delete 运算符正确析构动态对象。
例,普通析构函数在删除动态派生类对象的调用情况
#include<iostream>
using namespace std ;
class A {
public:
virtual~A()
{
cout << "A::~A() is called.\n" ; }
} ;
class B : public A {
public:
~B()
{
cout << "B::~B() is called.\n" ; }
} ;
int main() {
A *Ap = new B ; B *Bp2 = new B ;
cout << "delete first object:\n" ;
delete Ap;
cout << "delete second object:\n" ;
delete Bp2 ;
}
四.纯虚函数和抽象类
1.纯虚函数是一种特殊的虚函数,是一个在基类中说明的虚函数,在基类中没有定义,要求任何派生类都定义自己的版本
2.纯虚函数为各派生类提供一个公共界面
3. 纯虚函数说明形式:
virtual 类型 函数名(参数表)= 0 ;
4. 一个具有纯虚函数的基类称为抽象类。
5.纯虚函数的作用:
在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。
例.简单图形类
#include<iostream>
using namespace std ;
#include"figure.h"
class figure
{
protected : double x,y;
public: void set_dim(double i, double j=0) {
x = i ; y = j ; }
virtual void show_area() = 0 ; };
class triangle : public figure
{
public :
void show_area()
{
cout<<"Triangle with high "