多态原理

原创 2007年09月26日 16:51:00

因为多态java和c++有共通之处,先来看c++的,再来看java的。

以下内容摘自李鑫深入浅出C++虚函数表

-------------------------------------------------

为什么要了解虚函数表

了解虚函数表对理解C++实现多态的机制会有更深的了解,对对象的内存布局会有更好的认识。

 

验证虚函数表的存在

C++中的structclass实际上是一样的)

C++中当一个类中存在virtual函数(虚函数)或者它的父类中存在虚函数,那么编译器就会为这个类生成虚函数表(virtual table,下面我用代码来验证这个事情。

首先写一个class

class A

{

};

cout<<sizeof(A)<<endl;

输出结果1,就是说这个类占1个字节(具体为什么要占1个字节我也不太清楚,应该就这么设计的吧,有高手请告诉我为什么)。

下面改写这个类,为其加上虚函数

class A

{

  public: virtual int add(int i);

};

cout<<sizeof(A)<<endl;

输出4

我们知道函数不会影响类的大小,函数的地址是另外被存在一片内存区域。

4个字节就是指向虚函数表的指针,编译器为有virtual函数的类加上去的,可以看到这是一个32位的指针,因为32位的操作系统的寻址范围是4G64位处理器这个数值应该是64位的,没有经过验证)。

这个指针指向的虚函数表也是一片内存,这里面存储这所有虚函数的地址。内存的情况可能如下:

虚函数表

A中的int add (int i)地址

。。。其他虚函数地址

如果类A的定义如下:

class A

{

public:

       int i;

       virtual int add(int i);

}

那么sizeof(A) == 8。所以类的大小等于vtablesize加上数据成员的size,如果他有父类,则还需要加上父类中数据成员的size。例如:

class B: public A

{

public:

       int k;

}

cout<<sizeof(B);

输出12

Bvtable (4bytes)+ B::k (4bytes) + A::i (4bytes) =12 bytes

多态的原理

多态是如何利用这个虚函数表实现的呢?看下面的代码:

struct Super

{

     int data;

     virtual int add(int i){return i;};

     virtual string toString()=0;

};

class Sub: public Super

{

public:

     string toString()

     {

         return string("Sub class");

     }

};

 

     Super* s = new Sub();

     cout<<s->toString()<<endl;

     delete s;

输出”Sub class”

Super vtable

Super:: add地址

Super::toString地址

Sub vtable

Super::add地址

Sub::toString地址

int data;

 

编译器会把虚表编译成上面的样式,注意两件事情:

第一,   虚函数表在类所有成员的最前面。

第二,   第二,Sub因为重写了toStringSub的虚函数表就记录者SubtoString的地址。

上面的程序Super* s = new Sub();

s实际指向的是Sub类对象的内存区域,所以调用方法的时候会根据这片内存记录的函数地址进行调用,多态就是这么实现的。

注:摘录完毕

----------------------------------------------

     既然多态是面向对象的三大本质特征之一(其它两个是数据抽象和继承),那么C++为什么不将方法调用的默认方式设置为动态绑定,而要通过关键字virtual进行标记呢?Bruce Eckel在《Thinking in C++》中提到,这是由于历史原因造成的,C++是从C发展而来的,而C程序员最为关心的是性能问题,由于动态绑定比静态绑定多几条指令,性能有所下降,如果将动态绑定设定为默认方法调用方式,那么很多C程序员可能不会接受,因此,C++就将动态绑定定位成可选的,并且作出保证:If you don't use it, you don't pay for it(Stroustrup)。
    但是,Java作为一个全新的完全面向对象的语言,并不存在向下兼容的问题,同时,Java的设计者也认为多态作为面向面向对象的核心,面向对象语言应该提供内置的支持,因此,Java将动态绑定作为方法调用的默认方式。
    下面,我们就详细地来了解一下Java是如何为多态提供支持的。 与C++一样,Java中也有一个存放实例方法地址的数据结构,在C++中,我们把它叫做VTable,而在java中方法表(Method Table),但是两者有很多相同之处:
     1、它们的作用是相同的,同样用来辅助实现方法的动态绑定。
     2、同样是类级别的数据结构,一个类的所有对象共享一个方法表。
     3、都是通过偏移量在该数据结构中查找某一个方法。
     4、同样保证所有派生类中继承于基类的方法在方法表中的偏移量跟该方法在基类方法表中的偏移量保持一致。
     5、方法表中都只能存放多态方法(Java中的实例方法,C++中是vitual方法)。

class Base ...{
 
int x = 1;
 
static int y=2;
 
int z=3;
 
int method() ...{
  
return x;
 }

}


class Subclass extends Base ...{
 
int x = 4;
 
int y=5;
 
static int z=6;
 
int method() ...{
  
return x;
 }

}


public class Test ...{
 
public static void main(String[] args) ...{
  Subclass s
=new Subclass();
  System.out.println(s.x 
+ " " + s.y +" "+ s.z);
  System.out.println(s.method());
  
  Base b 
= (Subclass)s;
  System.out.println(b.x 
+ " " + b.y +" "+ b.z);
  System.out.println(b.method());
 }

}



运行结果:
4 5 6
4
1 2 3
4

分析上以上代码,我们知道实例方法才有多态的,在运行时动态绑定。而实例变量或类变量则没有动态绑定的,是在编译是就决定了。所以s.x s.y s.z都是Subclass对象相应的值。而b.x b.y b.z都是Base对象相应的值。

 

多态

java编程思想第七章

多态机制原理解析--从内存角度分析

回头看多态,又有了新的认识。 理解多态主要搞清楚以下几个问题就可以了:(以父类Pet,子类Dog为例) 1.为什么可以用表达式 Pet p1= new Dog(); //为什么可以用父类的引用指向...
  • csp277
  • csp277
  • 2015年11月10日 14:59
  • 750

Java技术----多态的实现原理

0.前言 多态在Java技术里有很重要的地位,在面试中也会经常被问到。 多态的使用大家应该都比较了解,但是多态的实现原理就有点抽象了,查了很多很多资料,连续几天断断续续的看,有时候看着...

多态的编译器实现原理

  • 2011年12月26日 21:25
  • 32KB
  • 下载

JAVA核心,内存分配原理,多态

  • 2011年11月06日 18:42
  • 33KB
  • 下载

C++(多态实现原理)函数重写,重载,重定义

多态的实现原理:          首先介绍下函数重写 重定义 重载的区别; 函数重写:          发生在父类和子类之间,子类将父类中的同名函数进行了覆盖,如果在函数前面含有virtual那么...

Java技术——多态的实现原理

0.前言 多态在Java技术里有很重要的地位,在面试中也会经常被问到。 但是多态太抽象了,查了很多很多资料,连续几天断断续续的看,有时候看着看着就走神了。毕竟太抽象,哈哈~ 不过依然硬着头皮看下来了(...

多态实现原理-虚函数表内存分析及虚基类表的内存分析

看了深入探索C++对象模型后的一些感悟 1:虚函数表内存分析 每一个类对象的内存由nostatic data member和指向虚数表的指针之和决定。 class A{ private: int a;...

C++ 多态(迟绑定)原理

今天看到一篇帖子关于虚函数的问题,原以为自己已经对c++虚函数,多态了解的不错了,但是,还是发现有一些模糊点,所以,又回头重新总结了一番。 有了不小的收获,下面,就和大家一起来分享一下,也希望对...
  • hezeshi
  • hezeshi
  • 2014年05月28日 10:58
  • 361
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多态原理
举报原因:
原因补充:

(最多只允许输入30个字)