zoukankan      html  css  js  c++  java
  • 指向NULL的类

    引出:写个类A,声明类A指针指向NULL,调用类A的方法会有什么后果,编译通过吗,运行会通过吗?

    (在VS2008与VC++的情况下) 有错误欢迎批评指正!

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    
    class base{
        int a;
    public:
        void fun(){
            printf("base fun
    ");
        }
    };
    
    
    int main(){
        base *b=NULL;
        b->fun();
    }

    看到这个的时候,一定以为运行会报错吧。

    但是奇迹般的,编译器输出了:base fun

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    
    class base{
        int a;
    public:
        virtual void fun(){
            printf("base fun
    ");
        }
    };
    
    
    int main(){
        base *b=NULL;
        b->fun();
    }

    在看这个代码,还以为会输出base fun么,又错了,运行报错!

    为什么会是这个结果?

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    
    class base{
        int a;
    public:
        virtual void fun(){
            printf("base fun
    ");
        }
            void fun2(){
            printf("base fun
    ");
        }
    };
    
    
    int main(){
        base *b=NULL;
        b->fun();
        b->fun2();
    }

    可以发现,一个是虚函数,一个普通函数

    在观察下内存中得情况:

    发现果然虚函数还没在内存中,而fun2已经在内存中了

    在看看汇编:

    明显发现虚函数的调用比普通函数多了好几个步骤,

    ecx 中放的this 指针,所以this=0(NULL),但是普通函数fun2放在全局内存区,所以可以访问

    而虚函数是根据虚函数表寻找的,这时没有虚函数表,自然就没法查到虚函数的地址了

    感谢 hoodlum1980 更详细的说明:因为非虚函数的地址对编译期来说“静态”的,也就是函数地址在编译期就已经确定了,实例地址对于非虚函数只是那个 this 指针参数。所以只要不访问类的实例数据就没什么问题。而虚函数的地址,是先到实例的地址前面去查找它的虚函数表所在的地址。然后从虚函数表里取出该函数所对应的元素(虚函数表是一个函数指针数组)来call的。(当然一个已知的类的虚函数表的内容也是编译期静态的,但不同类的虚函数表内容不同,即运行时多态的基础)所以实例如果为NULL,是个有特殊意义的值,是会触发运行时错误的。

    总结:类中的虚函数是动态生成的,由虚函数表的指向进行访问,不为类的对象分配内存,就没有虚函数表就无法访问。

       类中的普通函数静态生成,不为类的对象分配内存也可访问。

  • 相关阅读:
    Linux下命令设置别名--alias(同实用于mac)
    mac 下配置连接Linux服务器方法,上传下载文件操作
    Jdbc和工具类
    MySQL和数据库
    validate和bootstrap学习
    jQuery学习
    JavaScripe学习
    CSS学习
    HTML学习
    Metail Design入门(一)
  • 原文地址:https://www.cnblogs.com/huhuuu/p/3463109.html
Copyright © 2011-2022 走看看