zoukankan      html  css  js  c++  java
  • (转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考

    昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下:

    class D
    {
    public:
        void printA()
        {
            cout<<"printA"<<endl;
        }
        virtual void printB()
        {
            cout<<"printB"<<endl;
        }
    };


    main函数调用:

    D *d=NULL;
    d->printA();
    d->printB();

    输出结果是?

    当时想的是对象d直接初始化为NULL,非虚的成员函数没有地址,应该找不到,而virtual成员函数,由于对象会有指向虚拟函数表的指针-vptr,指向virtual函数列表的虚拟函数表,这样应该能够取到地址(实际上,这个virtual函数的printB最应该想到是直接崩溃,因为d指向NULL,即地址为0x00000000,再去找虚地址指针,肯定是不允许的)。

     

    下面具体分析一下吧

    先看一下类的成员函数的情况,

     

     

    类A、B、C三个类,一个是什么都没有的真的空类,一个是有成员函数的类,最后一个是带有虚函数的类。

    class A
    {
    
    };
    class B{
    public:
        B(){}
        ~B(){}
    };
    class C
    {
    public:
        C(){}
        virtual ~C(){}
    };

    那他们分别咱的内存大小是多少呢?

    cout<<"A="<<sizeof(A)<<endl;
    cout<<"B="<<sizeof(B)<<endl;
    cout<<"C="<<sizeof(C)<<endl;

    32位windows xp机器上测试结果:

    A=1

    B=1

    C=4

    从A和B的比较可以看出成员函数是不占用类空间的,再具体一个例子:

    class E{
    public:
        E(){}
        ~E(){}
    private:
        int m_data;
        char c;
    };


    sizeof(E)在32位机器上输出结果,如果不考虑对齐 为5,考虑则为8,可见和上面B类的预期一致。

     

        我们可以说,静态数据成员和静态成员函数时类的一部分,而不是对象的一部分(谭老师说的)。

    当我们实例化一个对象的时候,因为这个对象是用类定义的,那么它理所当然拥有了这个类的数据和函数。但是,一般情况下,不同的对象,他们的的数据值不同,但是函数的代码都相同。所以,为了节约存储空间(想象一下我们如果定义了100个对象,那么用100段内存空间存储相同的代码,岂不是很浪费?),我们让成员函数的代码共享。

          我们把成员函数的代码存储在对象空间之外。换句话说,成员函数的代码,都不占据对象的存储空间。它会被存在其他地方。

          所以类的成员函数,对于类来讲。一方面是逻辑上的“属于”,一方面是物理上的“不依赖“。

          回到思考题上来,对于非静态成员函数来说,它当然是对象的一部分。(只是因为存储方式上的特殊性,容易让人误解!)

     

     

    回答开头问题:

    类中包括成员变量和成员函数
    new出来的只是成员变量,成员函数始终存在
    所以如果成员函数未使用任何成员变量的话,不管是不是static的,都能正常工作

    一个对象的空间=所有成员变量的大小

    如果这个对象的类有虚函数的话,还可能多一个指向虚表的指针

    所有函数存放在独立于对象的存储空间内
    对象调用函数时,对静态成员函数直接调用不存在问题,对成员函数需要把自己以this指针传给函数以指明以哪个对象调用

    所以用未初始化的指针调用静态成员函数、或者调用未使用任何成员变量的成员函数(即未用到this指针)

    从理论上都是可行的,至于具体支不支持看各个编译器吧

     

    思考:

    main函数中,如果

    D d;//=NULL;
        d.printA();
        d.printB();

    调用呢?

    都能正常输出,d在栈上。。。

  • 相关阅读:
    svn command line tag
    MDbg.exe(.NET Framework 命令行调试程序)
    Microsoft Web Deployment Tool
    sql server CI
    VS 2010 One Click Deployment Issue “Application Validation did not succeed. Unable to continue”
    mshtml
    大厂程序员站错队被架空,只拿着五折工资!苟活和离职,如何选择?
    揭秘!Windows 为什么会蓝屏?微软程序员竟说是这个原因...
    喂!千万别忘了这个C语言知识!(~0 == -1 问题)
    Linux 比 Windows 更好,谁反对?我有13个赞成理由
  • 原文地址:https://www.cnblogs.com/balingybj/p/4764739.html
Copyright © 2011-2022 走看看