美文网首页
(GeekBand)C++面向对象浅谈

(GeekBand)C++面向对象浅谈

作者: 东方未曦 | 来源:发表于2016-06-06 09:39 被阅读49次

    1.一个类的对象所占的内存空间

    一个Class对象需要的内存空间主要包括以下三个部分:
    1.非静态成员变量总合(静态变量不占用类的内存)
    2.编译器作出的数据对齐处理
    3.支持虚函数产生的虚指针(普通函数不占用类的内存)

    举例分析:

    1.空类
    class Test
    {...};
    

    编译器会给空类创建一个1byte的空间,因此空类对象所占的额内存为一个字节。

    2.只含有成员变量的类
    class Complex
    {
    private: 
        int re;
        int im;
        static int number;
    };
    

    这时候类的对象的大小就变成了8bytes,因为有两个非静态成员变量。
    而static变量在内存中始终占用相同的一块内存,因此在对象中占用内存。

    class Complex
    {
    private: 
        char user;
        int re;
        int im;
        static int number;
    };
    

    这个类相对于上一个多了一个char变量,所有变量加起来为9bytes。
    而为了内存对齐,需要进行扩展,因此最后结果是12bytes。

    3.含有虚函数的类
    class Test
    {
    public: 
        Test( ) {...}
        virtual ~Test( ) {...}
    };
    

    2.虚函数表解析

    1.简介

    C++中的虚函数的作用主要是实现了多态。
    多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,是一种泛型技术。
    泛型技术指试图使用不变的代码来实现可变的算法。

    2.虚函数表

    虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。
    在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了 这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
    编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

    假设有下面这个类:

    class Base {
    public:
        virtual void f( ) { cout << "Base::f" << endl; }
        virtual void g( ) { cout << "Base::g" << endl; }
        virtual void h( ) { cout << "Base::h" << endl; }
    };
    

    我们可以通过Base的实例来得到虚函数表。

        Base b;
        cout << "虚函数表地址:" << (int*)(&b) << endl;
        cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;
    

    可得到:
    虚函数表地址:0012FED4
    虚函数表 — 第一个函数地址:0044F148

    相关文章

      网友评论

          本文标题:(GeekBand)C++面向对象浅谈

          本文链接:https://www.haomeiwen.com/subject/cwirdttx.html