zoukankan      html  css  js  c++  java
  • 使用函数指针模拟C++多态

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Base
     5 {
     6 public :
     7     void display()
     8     {
     9         cout << "Base display" << endl;
    10     }
    11 
    12     void (Base :: **VTable)();//指向虚表的函数指针
    13     int a;
    14 }; 
    15 
    16 class Derived : public Base
    17 {
    18 public :
    19     void display()
    20     {
    21         cout << "derived display" << endl;
    22     }
    23 };
    24 
    25 void test(Base *pointer)
    26 {
    27     void (Base :: *pFunc)() = (void(Base :: *)())pointer->VTable[0];
    28     (pointer->*pFunc)();
    29 }
    30 
    31 int main()
    32 {
    33     //多态是通过多余的存储空间存储了虚函数的地址,通过函数指针来实现虚函数的调用
    34     //1.分配空间+4,成员变量从+4的位置开始了。最上面的控件保留一个指针。
    35     //2.为该指针指向的地址分配一块存储空间
    36     //3.将所有虚函数的地址存储到这块存储空间中,这个存储空间称为虚表

        //初始化工作,也就是编译器帮我们做的事 37 Derived *derived = new Derived(); 38 derived->VTable = (void(Base :: **)())new int[1]; 39 derived->VTable[0] =(void(Base :: *)()) &Derived :: display;//初始化工作 40 test(derived); 41 42 Base *base = new Base(); 43 base->VTable = (void(Base :: **)())new int[1]; 44 base->VTable[0] = (void(Base :: *)()) &Base :: display; 45 test(base);
    48 system("pause"); 49 return 0; 50 }

     基类如果不使用虚函数virtual构成多态的话,使用sizeof得到Base的大小为4,如下图(Base中的成员变量只有一个int a,使用32位编译器,如下代码中的基类,只是演示使用)

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Base
     5 {
     6 public :
     7     void display()
     8     {
     9         cout << "Base display" << endl;
    10     }
    11 
    12     int a;
    13 }; 
    14 
    15 class Derived : public Base
    16 {
    17 public :
    18     void display()
    19     {
    20         cout << "derived display" << endl;
    21     }
    22 };
    23 
    24 int main()
    25 {
    26     cout << "Base's size is " << sizeof(Base) << endl;
    27     system("pause");
    28     return 0;
    29 }

    如果使用virtual构成虚函数,再使用sizeof测试基类的大小,会发现基类大小增加了4

    #include <iostream>
    using namespace std;
    
    class Base
    {
    public :
        virtual void display()
        {
            cout << "Base display" << endl;
        }
    
        int a;
    }; 
    
    class Derived : public Base
    {
    public :
        void display()
        {
            cout << "derived display" << endl;
        }
    };
    
    int main()
    {
        cout << "Base's size is " << sizeof(Base) << endl;
        system("pause");
        return 0;
    }

     

    那这个 4byte的空间是什么东西?是干什么用?

    经过向父类加入多个虚函数,测试之后发现还是只是增加4byte,那么只有指针可以做到。

    这个指针是一个二级指针,指向一个虚表的地址,虚表中存储的是父类与子类同名函数的地址。(比较复杂,我也只能理解到这个地步,所以表达更是low)

    /**********************************************************************************2017/7/20,以后有了更深的理解再继续更新******************************************************************************************/

  • 相关阅读:
    Java Scanner
    Java 继承
    什么叫异常?什么叫错误? 如何捕获异常? 如何抛出异常? 说说finally和final的区别! 什么是JDK?什么是JRE?说说它们之间的区别? 说说字符常量和字符串常量的区别
    数据分析三剑客之Pandas时间序列
    Css样式布局之Flex弹性盒子布局
    memcached的安装和使用
    Flask 第十八话之Restful API
    Flask 第十七话之信号
    Flask 第十六话之钩子函数
    Flask 第十五话之请求上下文及全局全局存储g对象
  • 原文地址:https://www.cnblogs.com/SimonKly/p/7209910.html
Copyright © 2011-2022 走看看