日期:2014-05-20  浏览次数:20684 次

关于多态性的动态绑定问题。。对象调用方法的执行过程。
对象调用方法的过程我是这样认为的思路很混乱希望有路的大虾指导下。
      1   虚拟机生成所需类的方法,表中列出的类中定义的所有方法和继承的方法
      2   在调用方法的时候,虚拟机提出调用当前方法的对象的实际类型的方法表
      3   虚拟机搜索定义该方法标签(调用的方法)的类,      
      4   虚拟机找出于实际类型最合适的类
         
          什么时候发生重载解析?
          静态绑定在什么时候执行呢?
         
 
     
      PS:对象调用方法的执行过程我说的也不是很清楚,逻辑上有些混乱,大家看得我上面说的话一定很累`,其实我想表达的意思就是:
                我想知道编译器在进行对象调用方法的执行过程?

------解决方案--------------------
编译和运行不管在哪种语言和哪类操作系统上都一样。问题的实质是:编译过程是编译器的事,与运行无关;而运行是操作系统的事,与编译无关。比如你问的“想知道编译器在进行对象调用方法的执行过程?”,这个问题本来就不对,编译器只是编译,调用是操作系统的事(对java是虚拟机的事),编译器编译时它顶多只关注下要静态绑定代码模块(函数或数据)还是动态绑定,静态绑定的意思是编译时它就把需要访问的变量和函数地址安排好了,当然开始是相对逻辑地址,待系统平台把程序代码搬到内存上运行时才把这些地址转换成实际的物理地址;而动态绑定就是编译时没有事先安排好要访问的变量或函数的实际地址位置,而是插入一些信息,这些信息一般是一些表,在程序运行时先调用这些表,再根据表里的指示信息去进一步调用相关对象(数据或函数),所谓面向对象的多态性或是所谓的虚函数实际就是这样解决的。
这里再想说下你提到的类的问题,类的定义实际只是语言层面的概念,即在语言环境里才有效,一旦编译成代码,类的定义就消失了,剩下的只是赤裸的变量和函数了,对于同一类里的变量和函数,编译时编译器就把它们做成相互调用的关系,比如某变量就变成了某函数的参数等,因此在源代码里我们常可写成直接去访问一个对象的变量,实际编译后就变成了调用这个变量的函数了,或者通过这个变量携带的一些信息表进一步指示去调用相关的函数,总之最后还是得通过调用函数才会起实际的作用。
最后你问的什么时候进行静态绑定,以上说很清楚了,就是在编译时就搞定。什么时候发生重载解析?那一定是运行的时候了。我想大致就这么回事吧,这也是本人的小见,请高手进一步指正。
另外以上说的编译和运行无关只是相对而言,实际编译软件的开发肯定是要根据其所基于的操作系统来开发的,实际是肯定要根据操作系统所能提供的API功能来做,而不可能超越它;如果操作系统是基于组件的模型的(如Windows的com及java系统的组件体系等),那你要想基于其上运行,开发语言就得依照它的组件规则来开发。另外需要说明的是,如果系统平台天生具备面向对象特性的,那我们进行语言编译器开发时就可直接利用它的特性,编译器需要包含的功能就少些,否则编译器就相对复杂,因为这意味着要在开发层面上添加许多支持面向对象的特性,这是没办法的事,因为操作系统不支持啊。
另外想说下关于有提到的构造函数问题。类也是数据类型,本质上声明一个类跟声明一个基本数据类型是一样的,如 "class 类名 "与 "int 变量名 "是一样的,都是为变量申请空间或是赋值,但类型发展到类时我们就喜欢在类里放入一些构造和析构函数,这就不得不涉及动态和静态创建(实际是申请)对象(实际是内存空间)问题,为什么要动态和静态的问题,这都是出于节省内存空间,也许 "int a "需要内存空间小,所以很少人去想怎么动态创建和销毁它的问题,但类的体积可大可小,大的可以很大,如果不考虑动态创建和销毁问题,一个程序运行下来可能占用的内存空间就很大,所以在后来的编译器上就加入了动态创建和销毁对象的机制,这一机制就是“构造/析构函数”机制。实际上如果你不想用这些机制也行,那你就给类做静态连编吧,这样在编译时就直接创建对象空间插入二进制代码中,作为程序不可分离的一部分,如此而已。