c++ 对象模型 9

一 。虚函数指针在类的成员变量之前
    class A{
    public:
        int a;
        virtual void func(){
            cout << "virtual func" <<endl;
        }
    }
    int main(){
        A aobj;

        char* p1 = reinterpret_cast<char*>(&aobj);
        char* p2 = reinterpret_cast<char*>(&(aobj.a));
        if (p1 == p2) {
            cout << "虚指针在下" << endl;
        }
        else
        {
            cout << "虚指针在上" << endl;
        }
    }

二。 一个类只有包含虚函数才会存在虚函数表,同属于一个类对象共享虚函数表,但是有各自的vptr
        指向的虚函数表首地址相同。
    父类中有虚函数子类中就有虚函数,父类中有虚函数表子类中也有虚函数表,继承父类的
    不管父类还是子类,都只有一个虚函数表,不能认为子类中有一个虚函数表 + 父类中有一个虚函数表
    即便子类中的virtual关键字去掉 依然也是虚函数
    如果子类中完全没有新的虚函数,则我们可以认为子类的虚函数表和父类的虚函数表相同
        但是只是内容相同,这个两个表在内存中处于不同的位置, 这是内容相同的两个表

三。 一个对象 如果它的类有多个基类则有多个虚指针(是两个虚指针,而不是两个虚函数表
    在多继承中,对应各个基类的vptr按继承顺序一次防止在类的内存空间中,且子类与第一个基类公用一个vptr
    第二个基类有自己的vptr
        
四。 虚函数表指针什么时候创建出来的
    // vptr 跟着对象走 所以对象什么时候创建出来 vptr就什么时候创建出来
    // 实际对于这种有虚函数的类,在编译的时候,编译器就会网构造函数中添加vptr赋值的代码
    // 当程序运行,遇到创建对象的代码,执行对象的构造函数,那么这个构造函数里有给对象的vprt赋值的语句
    
五。 虚函数表什么时候创建。
    实际虚函数表是编译器在编译期间(不是运行期间  就为每个类确定了对应的虚函数表vtbl的内容
    也是编译器在编译期间在对应的类构造函数中添加vprt赋值的代码
    当程序运行,遇到创建对象的代码,执行对象的构造函数,那么这个构造函数里有给对象的vprt赋值的语句
    
六 单纯的类不纯时引发的虚函数调用问题

    单纯的类:比较简单的类 尤其不包含虚函数和虚基类
    某些情况下编译器回望类内部增加一些我们看不到,但是真实存在的成员变量(隐藏成员变量) 有了这种变量的类
    就不单纯了
    同时这种隐藏的成员便改良的增加(使用)或者赋值的时机,往往都是在执行构造函数和拷贝构造函数之前进行
    这时候代码中使用memset memcpy 这种函数就会把虚指针清零操作,new操作会触发异常 

为什么直接定义对象就可以使用?
静态联编 : 我们编译器的时候就能确定调用哪个函数,把调用语句和被调用函数绑定到一起
动态联编 : 在程序运行时,根据具体情况,动态的把调用语句和被调用函数绑定到一起,
            动态联编一般只有在多态和虚函数情况下才存在
在直接定义一个对象的时候编译器在进行静态联编 已经确定了具体调用哪个函数 即使没有虚函数表也能正常使用
单纯的调用虚函数 不是多态  只有指针和引用才有多态 所以new会出问题

所以虚函数 多态其实是给函数和指针准备

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值