动态绑定与静态绑定
为了支持c++的多态性,才用了动态绑定和静态绑定。理解他们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误。
需要理解四个名词:
1、对象的静态类型:对象在声明时采用的类型。是在编译期确定的。
2、对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。
关于对象的静态类型和动态类型,看一个示例:
1 class B
2 {
3 }
4 class C : public B
5 {
6 }
7 class D : public B
8 {
9 }
10 D* pD = new D();//pD的静态类型是它声明的类型D*,动态类型也是D*
11 B* pB = pD;//pB的静态类型是它声明的类型B*,动态类型是pB所指向的对象pD的类型D*
12 C* pC = new C();
13 pB = pC;//pB的动态类型是可以更改的,现在它的动态类型是C*
3、静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
4、动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。
1 class B
2 {
3 void DoSomething();
4 virtual void vfun();
5 }
6 class C : public B
7 {
8 void DoSomething();//首先说明一下,这个子类重新定义了父类的no-virtual函数,这是一个不好的设计,会导致名称遮掩;这里只是为了说明动态绑定和静态绑定才这样使用。
9 virtual void vfun();
10 }
11 class D : public B
12 {
13 void DoSomething();
14 virtual void vfun();
15 }
16 D* pD = new D();
17 B* pB = pD;
让我们看一下,pD->DoSomething()和pB->DoSomething()调用的是同一个函数吗?
不是的,虽然pD和pB都指向同一个对象。因为函数DoSomething是一个no-virtual函数,它是静态绑定的,也就是编译器会在编译期根据对象的静态类型来选择函数。pD的静态类型是D*,那么编译器在处理pD->DoSomething()的时候会将它指向D::DoSomething()。同理,pB的静态类型是B*,那pB->DoSomething()调用的就是B::DoSomething()。
让我们再来看一下,pD->vfun()和pB->vfun()调用的是同一个函数吗? 是的。因为vfun是一个虚函数,它动态绑定的,也就是说它绑定的是对象的动态类型,pB和pD虽然静态类型不同,但是他们同时指向一个对象,他们的动态类型是相同的,都是D*,所以,他们的调用的是同一个函数:D::vfun()。
上面都是针对对象指针的情况,对于引用(reference)的情况同样适用。
指针和引用的动态类型和静态类型可能会不一致,但是对象的动态类型和静态类型是一致的。 D D; D.DoSomething()和D.vfun()永远调用的都是D::DoSomething()和D::vfun()。
至于那些事动态绑定,那些事静态绑定,有篇文章总结的非常好:
我总结了一句话:只有虚函数才使用的是动态绑定,其他的全部是静态绑定。目前我还没有发现不适用这句话的,如果有错误,希望你可以指出来。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 利用TFRecords存储于读取带标签的图片
- matlab sum函数
- [tensorflow损失函数系列]softmax_cross_entropy_with_logits
- RESTful API 设计最佳实践
- Spring 是如何解决循环依赖的?
- 移动webhead参数
- 看了这篇泛型,下次设计链表别傻傻的用int 表示node节点的值了
- 标准TensorFlow格式 TFRecords
- LeetCode 05最长回文子串
- 基于NCNN的3x3可分离卷积再思考盒子滤波
- [译]Buidler 新手教程
- tf.train.shuffle_batch函数解析
- 网页小图标Favicon
- ASP.net Core MVC项目给js文件添加版本号
- 多目标优化非支配关系实现