zoukankan      html  css  js  c++  java
  • *** C++虚函数表原理相关代码

    #include <iostream>
    
    using namespace std;
    
    class Test{
    public:
        void t(void){};
    };
    
    class Base {
    public:
        virtual void f() {cout<<"base::f"<<endl;}
        virtual void g() {cout<<"base::g"<<endl;}
        virtual void h() {cout<<"base::h"<<endl;}
    
        int n;
    };
    
    class Derive : public Base{
    public:
        void g() {cout<<"derive::g"<<endl;}
    };
    
    
    int main () {
        cout<<"size of Base: "<<sizeof(Base)<<endl;
        cout << "size of Test: " << sizeof(Test)<<endl;//Test类中没有虚函数,因此没有虚函数表
    
        typedef void(*Func)(void);
        Base b;
        Base *d = new Derive();
    
        Func f=NULL, g=NULL, h=NULL; 
        
        if (sizeof(void*) == sizeof(int))
        {
            int* pvptr = reinterpret_cast<int*>(d);
            int* vptr = reinterpret_cast<int*>(*pvptr); 
            f = (Func)vptr[0];
            g = (Func)vptr[1];
            h = (Func)vptr[2];
        }
        else if (sizeof(void*) == sizeof(long))
        {
            long* pvptr = reinterpret_cast<long*>(d);
            long* vptr = reinterpret_cast<long*>(*pvptr);  
            f = (Func)vptr[0];
            g = (Func)vptr[1];
            h = (Func)vptr[2];
        }
        else if (sizeof(void*) == sizeof(long long))
        {
            long long* pvptr = reinterpret_cast<long long*>(d);
            long long* vptr = reinterpret_cast<long long*>(*pvptr);
            f = (Func)vptr[0];
            g = (Func)vptr[1];
            h = (Func)vptr[2];
        }
    
        f();
        g();
        h();    
        
        return 0;
    }

     下面代码侧面说明,编译器在构造函数末尾处初始化vptr。所以如果在构造函数中调用virtual函数,动态绑定不会起作用,只会调用本类中的virtual函数:

    #include <iostream>
    using namespace std;
    
    class base
    {
    public:
        base()
        {
            doSth();
        }
        virtual void doSth(void)
        {
            cout << "I am Base" << endl;
        }
    };
    
    class derived: public base
    {
    public:
        virtual void doSth(void)
        {
            cout << "I am Derived" << endl;
        }
    };
    
    int main()
    {
        derived b;
        return 0;
    }

     下面代码是我自己写的读取虚函数表示例:

    #include <iostream>
    
    using namespace std;
    
    class Base{
    public:
        void func0(void)
        {
            cout << "Base::func0" <<endl;
        }
        virtual void func1(void)
        {
            cout << "Base::func1" << endl;
        }
        virtual void func2(void)
        {
            cout << "Base::func2" << endl;
        }
    
    private:
        int num1;
        int num2;
    };
    
    class Derived: public Base
    {
    public:
        void func0(void) //当Base中该函数声明为virtual,Derived中不写virtual也一样
        {
            cout << "Derived::func0" <<endl;
        }
        virtual void func1(void)
        {
            cout << "Derived::func1" << endl;
        }
        virtual void func3(void)
        {
            cout << "Derived::func3" << endl;
        }
    };
    
    typedef void (*Fun)(void);
    template <class T>
    inline Fun vTblItem(Base & obj, int i, T)
    {
        return (Fun)(*((T)(*(T)(&obj))+i));
    }
    Fun getVTblItem(Base & obj, int i)
    {
        void *p = NULL;
        if (sizeof(void*) == sizeof(int))
        {
            return vTblItem(obj, i, (int*)p);
        }
        else if (sizeof(void*) == sizeof(long))
        {
            return vTblItem(obj, i, (long*)p);
        }
        else if (sizeof(void*) == sizeof(long long))
        {
            return vTblItem(obj, i, (long long*)p);
        }
    }
    
    int main()
    {
        Derived b;
    
        getVTblItem (b,0)();
        getVTblItem (b,1)();
        getVTblItem (b,2)();
        
        Base & a = b;
        a.func0();
    
        return 0;
    }

    屏幕输出:

    Derived::func1                                                                                                                                                                     
    Base::func2                                                                                                                                                                        
    Derived::func3                                                                                                                                                                     
    Base::func0  

    如果将

    class Base{
    public:
        void func0(void)
      ... ...
    改为
    class Base{
    public:
        virtual void func0(void)
      ... ...
    则func0()也加入到了虚函数表中,并且是表中第1项。屏幕输出为:
    Derived::func0                                                                                                                                                                     
    Derived::func1                                                                                                                                                                     
    Base::func2                                                                                                                                                                        
    Derived::func0
  • 相关阅读:
    kafka 流式计算
    解决山地车令人讨厌的中轴异响及其他异响问题
    go语言通道详解
    使用Spring Cloud连接不同服务
    并发之痛 Thread,Goroutine,Actor
    用go语言实现线程池
    golang go语言通道类型的通道示例 通道的通道
    Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
    spring5 reactive
    Go 语言和 Scala 语言对比
  • 原文地址:https://www.cnblogs.com/superrunner/p/10116300.html
Copyright © 2011-2022 走看看