zoukankan      html  css  js  c++  java
  • 虚表/虚指针

    虚函数在c++中的实现机制就是用虚表和虚指针,但是具体是怎样的呢?从more effecive c++其中一篇文章里面可以知道:是每个类用了一个虚表,每个类的对象用了一个虚指针。具体的用法如下:

    1. class A  
    2. {  
    3. public:  
    4. virtual void f();  
    5. virtual void g();  
    6. private:  
    7. int a  
    8. };  
    9.   
    10. class B : public A  
    11. {  
    12. public:  
    13. void g();  
    14. private:  
    15. int b;  
    16. };  




    //A,B的实现省略

      因为A有virtual void f(),和g(),所以编译器为A类准备了一个虚表vtableA,内容如下:

    A::f 的地址
     A::g 的地址

    B因为继承了A,所以编译器也为B准备了一个虚表vtableB,内容如下:

    A::f 的地址
    B::g 的地址

    注意:因为B::g是重写了的,所以B的虚表的g放的是B::g的入口地址,但是f是从上面的A继承下来的,所以f的地址是A::f的入口地址。

    然后某处有语句 B bB;的时候,编译器分配空间时,除了A的int a,B的成员int b;以外,还分配了一个虚指针vptr,指向B的虚表vtableB,bB的布局如下:

    vptr : 指向B的虚表vtableB

    int a: 继承A的成员

    int b: B成员

     

    当如下语句的时候:
    A *pa = &bB;

    pa的结构就是A的布局(就是说用pa只能访问的到bB对象的前两项,访问不到第三项int b)
    重生之大文豪 www.dwhao.com
    那么pa->g()中,编译器知道的是,g是一个声明为virtual的成员函数,而且其入口地址放在表格(无论是vtalbeA表还是 vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa->vptr)[1](C语言的数组索引从0开始哈~)。

    这一项放的是B::g()的入口地址,则就实现了多态。(注意bB的vptr指向的是B的虚表vtableB)

    另外要注意的是,如上的实现并不是唯一的,C++标准只要求用这种机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每个编译器自己决定。

  • 相关阅读:
    《软件需求分析》阅读笔记
    03软件需求阅读笔记之一
    02软件需求阅读笔记之一
    01软件需求阅读笔记之一
    评价一下大家手头正在使用输入法或者搜索类的软件产品。
    05构建之法阅读笔记之一
    06构建之法阅读笔记之一
    03构建之法阅读笔记之一
    【秋招必备】Java中间件面试题(2021最新版)
    快手3面:说说傅里叶变换、拉普拉斯变换为什么要变换,它们之间的联系是什么!
  • 原文地址:https://www.cnblogs.com/jiangye/p/3494200.html
Copyright © 2011-2022 走看看