参考博客:http://bdxnote.blog.163.com/blog/static/8444235200911311348529/
1.什么是联编?
联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系;按照联编所进行的阶段不同,可分为静态联编和动态联编;
例如:
A类中有fun这个函数, B类中也有fun这个函数,现在我在类外的main函数里面调用fun 函数。
那么main函数就是函数调用,调用fun函数,
而A类中的fun函数和B类中的fun函数就是执行该操作的代码段,
所以现在联编就是实现两者的映射关系。
class A
{
void func() {cout<<"It's A"<<endl;
};
class B
{
void func() {cout<<"It's B"<<endl;
};
int main()
{
func();
}
联编就是决定将main函数中的func()的函数调用映射到A中的func函数还是B中的func函数的过程。
2.静态联编 和 动态联编 定义
静态联编:
是指联编工作是在程序编译连接阶段进行的,这种联编又称为早期联编;因为这种联编是在程序开始运行之前完成的;在程序编译阶段进行的这种联编又称静态束定;在编译时就解决了程序中的操作调用与执行该操作代码间的关系,确定这种关系又被称为束定;编译时束定又称为静态束定;
拿上面的例子来说,静态联编就是在编译的时候就决定了main函数中调用的是A中的func还是B中的func。一旦编译完成,那么他们的映射关系就唯一确定了。
动态联编:
编译程序在编译阶段并不能确切地知道将要调用的函数,只有在程序执行时才能确定将要调用的函数,为此要确切地知道将要调用的函数,要求联编工作在程序运行时进行,这种在程序运行时进行的联编工作被称为动态联编,或动态束定,又叫晚期联编;C++规定:动态联编是在虚函数的支持下实现的;
动态联编在编译的时候还是不知道到底应该选择哪个func函数,只有在真正执行的时候,它才确定。
静态联编和动态联编都是属于多态性的,它们是在不同的阶段进对不同的实现进行不同的选择;
其实多态性的本质就是选择。因为存在着很多选择,所以就有了多态。
3.静态联编
例子:
#include <iostream>
using namespace std;
class shape{
public:
void draw(){cout<<"I am shape"<<endl;}
void fun(){draw();}
};
class circle:public shape{
public:
void draw(){cout<<"I am circle"<<endl;}
};
void main(){
circle oneshape;
oneshape.fun();//输出“I am shape”
oneshape.draw();//输出“I am circle”
}
4.动态联编
虚函数的概念我在上一片文章中进行了详细介绍,这里不再展开。
虚函数是动态联编的基础;虚函数是成员函数,而且是非静态的成员函数;虚函数在派生类中可能有不同的实现,当使用这个成员函数操作指针或引用所标识的对象时,对该成员函数的调用采用动态联编方式,即:在程序运行时进行关联或束定调用关系;
动态联编只能通过指针或引用标识对象来操作虚函数;如果采用一般的标识对象来操作虚函数,将采用静态联编的方式调用虚函数;
如果一个类具有虚函数,那么编译器就会为这个类的对象定义一个指针成员,并让这个指针成员指向一个表格,这个表格里面存放的是类的虚函数的入口地址;比如:一个基类里面有一些虚函数,那么这个基类就拥有这样一个表,它里面存放了自己的虚函数的入口地址,其派生类继承了这个虚函数表,如果在派生类中重写/覆盖/修改了基类中的虚函数,那么编译器就会把虚函数表中的函数入口地址修改成派生类中的对应虚函数的入口地址;这就为类的多态性的实现提供了基础;
虚函数按照其声明顺序存放于虚函数表中;
父类的虚函数存放在子类虚函数的前面;
多继承中,每个父类都有自己的虚函数表;
子类的成员函数被存放于第一个父类的虚函数表中;