zoukankan      html  css  js  c++  java
  • 多态实现的原理------新标准c++程序设计

      “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定。例子:

    #include<iostream>
    using namespace std;
    class A{
    	public:
    		int i;
    		virtual void func(){};
    		virtual void func2(){};            //如果为只有一个去掉 virtual 关键字即virtual void func2(){};变为 void func2(){}; 输出结果不变 仍为 8,12 
    };                                                   //当 virtual 关键字都去掉时,结果才为 4,8
    class B :public 
    	int j;
    	void func(){}
    };
    int main(){
    	cout<<sizeof(A)<<","<<sizeof(B);
    };

      输出结果:

    8,12
    

      如果将程序中的 virtual 关键字去掉:

    #include<iostream>
    using namespace std;
    class A{
    	public:
    		int i;
    		void func(){};
    		void func2(){};
    };
    class B :public A{
    	int j;
    	void func(){}
    };
    int main(){
    	cout<<sizeof(A)<<","<<sizeof(B);
    };
    

      输出结果:

    4,8
    

      对比发现,有了虚函数以后,对象占用的存储空间比没有虚函数时多了4个字节。实际上,任何有虚函数的类及其派生类的对象都包含这多出来的4个字节,这4个字节就是实现多态的关键——它位于对象存储空间的最前端,其中存放虚函数表的地址。

      每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该表的任何对象中都放着该虚函数表的指针(可以认为这是由编译器自动添加到构造函数中的指令完成的)。虚函数表是编译器生成的,程序运行时被载入内存。一个类的虚函数表中列出了该类的全部虚函数地址。例如,在上面的程序中,类A对象的存储空间以及虚函数表(假定类A还有其他虚函数)如图

     

      类B对象的存储空间以及虚函数表(假定类B还有其他虚函数)如图

      多态的函数调用语句被编译成根据基类指针所指向的(或基类引用所引用的)对象中存放的虚函数表的地址,在虚函数表中查找虚函数地址,并调用虚函数的一系列指令。

      假设pa的类型是A*,则pa->func()这条语句的执行过程如下:

        (1)取出pa指针所指位置的前4个字节,即对象所属的类的虚函数表的地址(在64位计算机中,由于指针占8个字节,所以要取出8个字节)。如果pa指向的是类A的对象,则这个地址就是类A的虚函数表的地址;如果pa指向的是类B的对象,则这个地址就是类B的虚函数表的地址。

        (2)根据虚函数表的地址找到虚函数表,在其中查找要调用的虚函数的地址。不妨认为虚函数表是以函数名作为索引来查找的,虽然还有更高效的查找方法。如果pa指向的是类A的对象,自然就会在类A的虚函数表中查找A::func的地址;如果pa指向的是类B的对象,就会在类B的虚函数表中查出B::func的地址。类B没有自己的func2函数,因此在类B的虚函数表中保存的是A::func2的地址,这样,即便pa指向类B的对象,"pa->func2();"这条语句在执行过程中也能在类B的虚函数表中找到A::func2的地址。

        (3)根据找到的虚函数的地址调用虚函数。

      由以上过程可以看出,只要是通过基类指针或基类引用调用虚函数的语句,就一定是多态的。也一定会执行上面的查表过程,哪怕这个虚函数仅在基类中有,在派生类中没有。

     新标准c++程序设计

  • 相关阅读:
    expandafter
    又回到了kde
    朗读软件
    tex bookmarks
    vim命令执行时间
    vim,tex的编译
    utorrent
    火狐的扩展
    linux 无线指示灯闪
    tex溢出报警
  • 原文地址:https://www.cnblogs.com/l2017/p/7823498.html
Copyright © 2011-2022 走看看