C++之静态联编与动态联编及virtual关键字的作用
定义
将一个调用函数连接上正确的被调用函数,这个过程就叫做函数的联编,简称联编。在C++中,一共有两种联编的方式:
静态联编
#define:静态联编是指联编工作出现 在编译连接阶段。
特点:① 静态联编就是指被调用函数和执行调用函数之间的关系以及它们在内存中的地址在编译的时候已经确定好了,运行时不会发生变化。
② 由于对象不用对自身进行跟踪,因此速度浪费比较小,但是灵活性较差。
动态联编
#define:动态联编是指 在程序运行的时候才进行的联编工作。
特点:① 由于编译程序在编译阶段并不能确切知道将要调用的函数,只有在程序执行时才能确定将要调用的函数。要确切之道该调用的函数,就必须要求联编工作在程序运行时才能进行。
② 虽然可以追踪对象,灵活性较强,但是速度浪费严重。
virtual关键字的作用
首先,我们来看几个例子:
//例1 用父类对象的指针指向子类对象
#include <iostream>
using namespace std;class father
{
public:father(){};father(int i){age=i;}void print()const{cout<<"father's age is "<<age<<endl;}
protected: //protected声明的成员可以被派生类访问int age;
};class son:public father
{
public:son(){};son(int j){age=j;}void print()const{cout<<"son's age is "<<age<<endl;}
};int main()
{cout<<"一般情况:\n";father dad(56);dad.print();son boy(22);boy.print();cout<<"指针情况:\n";father *liu=new father(56);liu->print();son *uniqueliu=new son(22);//father *uniqueliu=new son(22);uniqueliu->print();
}
这个程序的运行结果:
上面这个结果很好理解吧,我就不解释了。但是如果我们这里把程序33行的注释去掉,把32行注释起来。那么程序运行的结果就会出现如下的情况:
这个就很奇怪了。我们的初衷是想用一个父类指针来指向一个子类对象。但是最后调用的print函数却是父类对象的。这个原因就是因为我们没有在父类中的print()前面加上关键字virtual的原因了。这是因为在函数print()函数前面加上了关键字virtual,就表示该函数是有多种形态的,说白了,就是这个print()函数可以被很多对象所拥有,而且各自实现的功能是不一样的,这样一来,就是先了多态。总结一下,我们只要在基类的成员函数前面加上virual,那么就算派生类的对象重新实现了同名函数,编译器就会自动判断是哪个对象调用了它,然后用该对象的同名函数,而不会采用基类的函数了。程序如下所示:
//例2 用父类对象的指针指向子类对象+virtual
#include <iostream>
using namespace std;class father
{
public:father(){};father(int i){age=i;}virtual void print()const{cout<<"father's age is "<<age<<endl;}
protected: //protected声明的成员可以被派生类访问int age;
};class son:public father
{
public:son(){};son(int j){age=j;}void print()const{cout<<"son's age is "<<age<<endl;}
};int main()
{cout<<"一般情况:\n";father dad(56);dad.print();son boy(22);boy.print();cout<<"指针情况:\n";father *liu=new father(56);liu->print();//son *uniqueliu=new son(22);father *uniqueliu=new son(22);uniqueliu->print();
}
这样,我们在程序的第10行上加上了virtual关键字。它就将基类的print()函数声明成了虚函数。这样一来,我们就可以调用子类的print()函数了,下图说明了真相:
virtual与联编之间的关系
相对于例1来讲,在这里面调用的关系就是静态联编,因为在程序的编译阶段就已经把对象和它们所指向的函数紧紧地联系在一起了,运行的时候自然就不会有任何改变。而对于例2来讲,由于在父类的print()函数前面加上了关键字virtual,那么这个时候父类中的print()函数就变成了虚函数,虚函数就可以实现运行时的动态联编。这是因为virtual会让编译器自动地区寻找与之对应的对象,所以输出才会如红框所示,“son's age is 22”。
特别注意一点!!!只有在 使用指针或者是引用的时候,才能够实现动态联编。
C++之静态联编与动态联编及virtual关键字的作用相关推荐
- 关于静态联编和动态联编
首先什么是联编? 通俗的来说联编就是函数调用(操作调用)与执行该操作(函数)的代码段之间的映射关系. 按照联编所进行的阶段不同可分为静态联编和动态联编 举个列子 #include<iostrea ...
- Cpp 对象模型探索 / 静态联编和动态联编
一.源码 #include <iostream>class Father { public:Father(){/*** 该处直接将该对象清零,意味着虚函数表指针亦被清零.*/memset( ...
- c++中的多态---1(多态概念,静态联编和动态联编,多态原理解析,重载,重写,重定义的对比)
多态的基本概念 多态是面向对象设计语言数据抽象和继承之外的第三个基本特征 多态性(polymorphism)提供接口与具体实现之间的另一层隔膜,从而将"what"和"ho ...
- C++静态联编与动态联编
目录 基本概念 举个栗子 基本概念 联编 就是将模块或者函数合并在一起生成可执行代码的处理过程(函数调用),按照联编所进行的阶段不同,可分为两种不同的联编方式:静态联编和动态联编. 函数调用和实现的过 ...
- C++的静态联编和动态联编
联编的概念 联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系. 意思就是这个函数的实现有多种,联编就是把调用和 ...
- 虚拟函数-1、静态联编与动态联编,引入虚函数
在实际开发工作中,为提高代码的重用性,编写通用的功能模块,往往需要设计处理几种不同对象的通用程序,如示例2.1所示. 示例清单2.1 #include "stdio.h" #inc ...
- 静态联编与动态联编之virtual的作用
=========================定义========================= 将一个调用函数连接上正确的被调用函数,这个过程就叫做函数的联编,简称联编.在C++中,一共有两 ...
- 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数
1.静态联编,是程序的匹配,连接在编译阶段实现,也称为早期匹配.重载函数使用静态联编. 2.动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编.switch语句和if语句是动态联编的例子. #i ...
- C++的动态多态,Virtual关键字的作用
1.虚函数 virtual用来修饰父类函数中的普通函数,子类可以通过重写(与父类中的普通函数同名同参数)来覆盖父类中的函数的输出结果,即程序在运行时调用的是子类中的函数而不是父类.注 ...
最新文章
- jsx怎么往js里传参数_实践Vue 3.0做JSX(TSX)风格的组件开发
- Nginx http和反向代理配置实例介绍
- unity NGUI 一些操作记录
- Java前端技术学习
- Java路径问题终于解决方式—可定位全部资源的相对路径寻址
- 在弹窗中新建一个遮罩层
- 【pytorch目标检测】开山之作:R-CNN算法解读
- 大批量数据导出到Excel
- 洛谷P1322 logo语言
- html网页设计字体变色,网页制作怎么改变字体颜色
- matlab钉子链条,MatLab的Galton钉板问题训练报告 终极版
- 一篇文章简单入门SpringCloud服务网关
- Android Studio Logcat 左边的工具栏不显示了 Show Toolbar
- clonezilla的可启动U盘的制作及使用
- ECCV 2020|3D-CVF多模态融合(LIDAR+CAMERA)
- ReactNative出现诸如以上的错误; ** is not defined.都是没有导入相应的库.
- 梦熊杯-十二月月赛-白银组题解-D.智慧
- Latex中多个表格的引用
- php错误报告和调试
- Android6.0boot解锁,Lenovo手机fastboot命令 解锁Bootloade 教程