C++学习 — 静态绑定与动态绑定

静态绑定,动态绑定算是一个比较偏的知识点,这个也是我在Effective C++这本书当中学习到的. 我觉得很有必要写一篇博客记

录.首先我们要知道静态类型和动态类型的概念:

静态类型:就是它在程序中被声明时所采用的类型(或理解为类型指针或引用的字面类型),在编译期确定;

动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。

接下来我引用Effective C++这本书中的例子,帮助理解:

  1. class Shape  
  2. {  
  3. public:  
  4.     enum shapeColor{Red,Green,Blue};  
  5.     //所有形状都必须提供一个函数,同来绘出自己.  
  6.     virtual void draw(shapeColor color = Red) const = 0;  
  7.     ...  
  8. };  
  9. class Rectangle : public Shape  
  10. {  
  11. public:  
  12.     //注意,赋予不同的缺省参数值,这真糟糕  
  13.     virtual void draw(shapeColor color = Green) const;  
  14. };  
  15. class Circle : public Shape  
  16. {  
  17. public:  
  18.   
  19.     virtual void draw(shapeColor color) const;  
  20.     //请注意,以上这么写则当客户以对象调用此函数,一定要指定参数值.  
  21.     //因为静态绑定下这个函数并不从其base继承缺省参数值  
  22.     //但若以指针(或reference)调用此函数,可以不指定参数值  
  23.     //因为动态绑定下这个函数会从其base继承缺省参数值  
  24.     ......  
  25.   
  26. };  
  27. Shape *ps;         // ps的静态类型为Shape*,它没有动态类型,因为它尚未指向任何对象;    
  28. Shape *pc = new Circle;      // pc的静态类型为Shape*,它的动态类型为Circle*;    
  29. Shape *pr = new Rectangle;   // pr的静态类型为Shape*,它的动态类型为Rectangle*;    
  30.   
  31.   
  32.   
  33. // 动态类型可以在程序执行过程中改变(通常是经由赋值动作):    
  34. ps = pc;                     // ps的动态类型如今是Circle*;    
  35. ps = pr;                     // ps的动态类型如今是Rectangle*;    

如果你想学习C/C++可以来这个群,首先是330,中间是859,最后是766,里面可以学习和交流,也有资料可以下载。

现在我们来理解何为静态绑定和动态绑定???

静态绑定:又名前期绑定(eraly binding),绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期;

动态绑定:又名后期绑定(late binding),绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在运行期;

比如常见的,virtual函数是动态绑定,non-virtual函数是静态绑定,缺省参数值也是静态绑定.

Virtual函数系动态绑定而来,意思是调用了一个virtual函数时,究竟调用那一份函数实现代码,

取决于付出调用的那个对象的动态类型:

  1. pc->draw(shape::Red); //调用Circle::draw(shape::Red)  
  2. pr->draw(shape::Red); //调用Rectangle::draw(shape::Red)  

其实这些都是老掉牙的知识点,但是今天我们带来了virtual函数不同的地方,缺省值! virtual函数是动态绑定的,而缺省参数值

为静态绑定. 意思是你可能会在"调用一个定义与derived class内的virtual函数"的同时,却使用base class为他所指定的缺省参

数值.

  1. pr->draw();        //调用Rectangle::draw(shape::Red)!  

此例当中,pr的动态类型为Rectangle*,所以调用的是Rectangle的virtual函数,一如你所预料.Rectangle::draw函数的缺省值应

该是Green,但由于pr的静态类型为shape*,所以此一调用的缺省参数值来自shape class而非Rectangle class!结局是这个函数调

用有这奇怪并且几乎没有人预料得到的组合,由shape class和Rectangle class的draw生命式各处一份力.

以上事实不只局限于"ps,pc和pr都是指针"的情况;即使把指针换成references问题依然存在.重点在于draw是一个virtual函数,而

它有个缺省参数值在derived class中被重新定义了.

为什么C++坚持以这种乖张的方式来运作呢? 答案在于运行期效率. 如果缺省参数值为动态绑定,编译器就必须有某种方法在运行

期为virtual函数决定适当的参数缺省值.这比目前实行的"在编译器决定"的机制更慢而且更复杂.为了程序的执行速度和编译器实

现上的简易度,C++做了这样的取舍,其结果就是你如今所享受的执行效率. 但是如果你重新定义了继承而来的缺省参数值,而且偏

偏在缺省参数值上面出现bug,那么你可能需要一个通宵都不一定调的出来.

时间: 2024-10-26 17:49:28

C++学习 — 静态绑定与动态绑定的相关文章

Java 静态绑定与动态绑定深入分析_java

Java 静态绑定与动态绑定           最近学习java 的知识,对java的静态绑定和动态绑定的学习很是模糊不清,然后就百度一下对其相应的知识进行了总结整理,帮助掌握这部分的知识 程序绑定的概念: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定. 静态绑定: 在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中的方法),此时由编译器或其它连接程序实现.例如:C. 针对jav

理解Java中的静态绑定和动态绑定_java

一个Java程序的执行要经过编译和执行(解释)这两个步骤,同时Java又是面向对象的编程语言.当子类和父类存在同一个方法,子类重写了父类的方法,程序在运行时调用方法是调用父类的方法还是子类的重写方法呢,这应该是我们在初学Java时遇到的问题.这里首先我们将确定这种调用何种方法实现或者变量的操作叫做绑定. 在Java中存在两种绑定方式,一种为静态绑定,又称作早期绑定.另一种就是动态绑定,亦称为后期绑定. 程序绑定的概念: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,

C++的静态绑定和动态绑定概述

C++在面向对象编程中,存在着静态绑定和动态绑定的定义,本节即是主要讲述这两点区分. 我是在一个类的继承体系中分析的,因此下面所说的对象一般就是指一个类的实例. 首先我们需要明确几个名词定义: 静态类型:对象在声明时采用的类型,在编译期既已确定: 动态类型:通常是指一个指针或引用目前所指对象的类型,是在运行期决定的: 静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期: 动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在运行期: 从上面的定义

Java中的静态绑定和动态绑定详细介绍_java

一个Java程序的执行要经过编译和执行(解释)这两个步骤,同时Java又是面向对象的编程语言.当子类和父类存在同一个方法,子类重写了父类的方法,程序在运行时调用方法是调用父类的方法还是子类的重写方法呢,这应该是我们在初学Java时遇到的问题.这里首先我们将确定这种调用何种方法实现或者变量的操作叫做绑定. 在Java中存在两种绑定方式,一种为静态绑定,又称作早期绑定.另一种就是动态绑定,亦称为后期绑定. 区别对比 1.静态绑定发生在编译时期,动态绑定发生在运行时 2.使用private或stati

php5学习笔记(转)

php5|笔记 作者: whhwq在phpv.net看到的感觉不错/*+-------------------------------------------------------------------------------+| = 本文为Haohappy读<<Core PHP Programming>> | = 中Classes and Objects一章的笔记 | = 翻译为主+个人心得 | = 为避免可能发生的不必要的麻烦请勿转载,谢谢 | = 欢迎批评指正,希望和所有

PHP5学习笔记

php5|笔记 第一节--面向对象编程 面向对象编程被设计来为大型软件项目提供解决方案,尤其是多人合作的项目. 当源代码增长到一万行甚至更多的时候,每一个更动都可能导致不希望的副作用. 这种情况发生于模块间结成秘密联盟的时候,就像第一次世界大战前的欧洲.//haohappy注:喻指模块间的关联度过高,相互依赖性太强.更动一个模块导致其它模块也必须跟着更动.想像一下,如果有一个用来处理登录的模块允许一个信用卡处理模块来分享它的数据库连接. 当然出发点是好的,节省了进行另一个数据库连接的支出.然而有

关于java中的静态绑定问题

问题描述 关于java中的静态绑定问题 请问 为什么 private方法和构造方法属于前期绑定呢?? 解决方案 Java静态绑定与动态绑定java动态绑定静态绑定java的动态绑定与静态绑定

PHP编程学习笔记

PHP使用header函数设置HTTP头的示例方法  代码如下 复制代码 //定义编码 header( Content-Type:text/html;charset=utf-8 ); //Atom header(Content-type: application/atom+xml); //CSS header(Content-type: text/css); //Javascript header(Content-type: text/javascript); //JPEG Image head

PHP对象模型深度探索[PHP专题]

面向对象编程是软件开发理论的一大进步,在此之前,大型应用软件项目是非常困难的,特别是那种源代码数十万行多人合作的项目,每一个改动都可能导致很多副作用产生,每个功能模块之间都可能导致其他模块出现错误.而在面向对象编程中,模块被组织成一个个对象.这些对象拥有方法和属性,从抽象的角度来看,方法是一个对象的所做的动作,而属性是对象的特性.从编程角度来看,方法就是函数而属性是变量.在一个理想化的面向对象体系中,每个部份都是一个对象,体系由对象及对象间通过方法来形成的联系构成. 每种语言提供了不同的途径来访