1 函数联编的定义
- 函数联编:将一个调用函数者联结上正确的被调用函数的过程,一般称为联编。
C++中的联编分两种:
(1)静态联编;
(2)动态联编;
2. 静态联编
2.1 静态联编的定义
- 成员函数必须声明为非virtual,即为非虚函数,该函数是静态联编;
- 静态联编:指联编工作出现在编译连接阶段,这种联编又称为早期联编;
- 编译程序:在编译阶段,被调函数和调用函数的关系以及它们的内存地址在编译时都已经确定好,运行时不再发生变化;
注:这样的好处是速度快,因为运行时候不用对各个对象的函数进行跟踪,只需要传递参数,执行确定好的函数并在函数调用完毕后清理内存即可。
2.2 在编译时的静态联编
- 在编译时所进行的静态联编又称为静态约束。
- 在编译时就处理好了程序中的操作调用与执行该操作代码间的关系,可行。
- 代码示例:
·
· #include<iostream>
·
· using namespacestd;
· class father
· {
· public:
· father(){}
· ~father(){}
· public:
· void run() const{cout<<"父亲可以跑万米"<<endl;}
· };
· class son : publicfather
· {
· public:
· son(){}
· ~son(){}
· public:
· void run() const{cout<<"儿子亲可以跑十万米"<<endl;}
· };
· int main()
· {
· father f;
· f.run();
· son s;
· s.run();
· system("pause");
· return 0;
· }
· =>父亲可以跑万米
儿子亲可以跑十万米
2.3 在运行时的静态联编
- 用指针在运行时动态地指向某个对象,然后再用该对象调用它的成员函数。
- 由于静态联编的对象与指针的关系在编译时就已确定,因此运行时再对它改变也是无效的,不可行。
- 代码示例:
·
· #include<iostream>
·
· using namespace std;
· class father
· {
· public:
· father(){}
· ~father(){}
· public:
· void run() const{cout<<"父亲可以跑万米"<<endl;}
· };
· class son : publicfather
· {
· public:
· son(){}
· ~son(){}
· public:
· void run() const{cout<<"儿子亲可以跑十万米"<<endl;}
· };
· int main()
· {
· int choice = 0;
· while(1)
· {
· cout<<"(1)father(2)son(3)quit:";
· father *p;
· bool quit = false;
· cin>>choice;
· switch(choice)
· {
· case 1:
· {
· p = new father;
· break;
· }
· case 2:
· {
· p = new son;
· break;
· }
· case 3:
· {
· quit = true;
· break;
· }
· default:
· {
· cout<<"请输入1~3之间的整数"<<endl;
· }
· }
· if(true == quit)
· {
· break;
· }
· p->run();
· }
· system("pause");
· return 0;
· }
· =>(1)father(2)son(3)quit:1
· 父亲可以跑万米
· (1)father(2)son(3)quit:2
· 父亲可以跑万米
(1)father(2)son(3)quit:3
3. 动态联编
3.1 动态联编的定义
- 成员函数必须声明为virtual,即为虚函数,该函数是动态联编;
- 动态联编:指联编工作出现在运行时阶段,这种联编又称为晚期联编;
- 编译程序:在编译阶段并不能确切知道将要调用的函数,只有在程序运行时才能确定将要调用的函数,为此要确切知道该调用的函数,要求联编工作要在程序运行时进行;
注:这样的好处是实现多态性和比较灵活,但是就要牺牲速度,因为每个函数调用在运行前是不可确定的,要随着用户的操作来执行相应的函数,相应地大大增加了系统的开销。
3.2 在编译时的动态联编
- 调用虚函数时,没有采用指针或引用,通过类对象调用虚函数,那么就无法实现动态联编,不可行。
- 代码示例:
· #include<iostream>
·
· using namespacestd;
· class father
· {
· public:
· father(){}
· ~father(){}
· public:
· virtual void run() const{cout<<"父亲可以跑万米"<<endl;}
· };
· class son : publicfather
· {
· public:
· son(){}
· virtual ~son(){}
· public:
· void run() const{cout<<"儿子亲可以跑十万米"<<endl;}
· };
· int main()
· {
· father f;
· son s;
· f.run();
· f = s;
· f.run();
· system("pause");
· return 0;
· }
· =>父亲可以跑万米
父亲可以跑万米
3.3 在运行时的动态联编
- 调用虚函数时,只有在使用指针或引用时,才能实现在运行时的动态联编,可行。
- 代码示例:
·
· #include<iostream>
·
· using namespacestd;
· class father
· {
· public:
· father(){}
· ~father(){}
· public:
· virtual void run() const{cout<<"父亲可以跑万米"<<endl;}
· };
· class son : publicfather
· {
· public:
· son(){}
· virtual ~son(){}
· public:
· void run() const{cout<<"儿子亲可以跑十万米"<<endl;}
· };
· int main()
· {
· father *f=new father;
· f->run();
· son s;
· father *p = &s;
· p->run();
· system("pause");
· return 0;
· }
· =>父亲可以跑万米
儿子亲可以跑十万米
参考文献:
[1]《C++全方位学习》范磊——第十三章
[2]《C++程序设计教程(第二版)》钱能——第五章、第六章、第七章
[3]《C++ Primer(第5版)》王刚 杨巨峰——第一章、第六章
[4] 百度搜索关键字:C++函数联编、虚函数、非虚函数、静态联编、编译时静态联编、运行时静态联编、动态联编、编译时动态联编、运行时动态联编