C++类的大小

一个空类class A{};的大小为什么是1,因为如果不是1,当定义这个类的对象数组时候A objects[5]; objects[0]和objects[1]就在同一个地址处,就无法区分。

单继承

#include<iostream>
using namespace std;
class A
{
public:
    virtual void aa(){}
private:
    char k[3];
};

class B: public A
{
public:
    virtual void bb(){}
};

int main()
{
    cout<<"A's size is "<<sizeof(A)<<endl;
    cout<<"B's size is "<<sizeof(B)<<endl;
    return 0;
}

vs和gcc下
执行结果:A's size is 8
              B's size is 8

说明:有虚函数的类有个virtual table(虚函数表),里面包含了类的所有虚函数,类中有个virtual table pointers,通常成为vptr指向这个virtual table,占用4个字节的大小。成员类B public继承于A,类B的虚函数表里实际上有两个虚函数A::aa()和B::bb(),类B的大小等于char k[3]的大小加上一个指向虚函数表指针vptr的大小,考虑内存对齐为8。

#include<iostream>
using namespace std;
class A
{
public:
    virtual void aa(){}
private:
    char k[3];
};

class B: public A
{
public:
    //virtual void bb(){}
};

int main()
{
    cout<<"A's size is "<<sizeof(A)<<endl;
    cout<<"B's size is "<<sizeof(B)<<endl;
    return 0;
}

vs和gcc下
执行结果:A's size is 8
              B's size is 8
说明:类B看上去没有虚函数,但实际上它有,只是没有重写,因为public继承,所以有从A继承过来的虚函数A::aa(),实际上类A和类B的虚函数表里的函数都是A::aa()。

#include<iostream>
using namespace std;
class A
{
public:
    virtual void aa(){}
    virtual void aa2(){}
private:
    char k[3];
};

class B: public A
{
public:
    virtual void bb(){}
    virtual void bb2(){}
};

int main()
{
    cout<<"A's size is "<<sizeof(A)<<endl;
    cout<<"B's size is "<<sizeof(B)<<endl;
    return 0;
}

vs和gcc下
执行结果:A's size is 8
              B's size is 8

说明:一个类里若有虚函数,无论有多少个虚函数都只有一个指向虚表的指针,虚表中的每一个表项保存着一个虚函数的入口地址。当调用虚函数时,先找到虚表中它对应的表项,找到入口地址再执行。对于直接单继承,无论类B中有无虚函数,由于它继承了类A,且类A里含有虚函数,因此如果类B有虚函数,那么它和类A的是在同一个属于类B的虚表里,这张虚表的虚函数为A::aa()、A::aa2()、B::bb()、B::bb2()。注意:类A里的私有成员在类B里仍占有内存。

多继承

#include<iostream>
using namespace std;
class A
{
public:
    virtual void aa(){}
    virtual void aa2(){}
private:
    char k[3];
};

class B
{
public:
    virtual void bb(){}
    virtual void bb2(){}
};

class C: public A,public B
{
public:
    virtual void aa(){} //重写了A的aa()
    virtual void cc(){}
};

int main()
{
    cout<<"A's size is "<<sizeof(A)<<endl;
    cout<<"B's size is "<<sizeof(B)<<endl;
    cout<<"C's size is "<<sizeof(C)<<endl;
    return 0;
}

vs和gcc下
执行结果:A's size is 8
          B's size is 4
          B's size is 12

说明:类A和B的大小就不解释了,参照上面。类C多重继承于A和B(有虚函数覆盖),那么类C的大小是多少?先看成员变量,有一个继承A的char k[3]。再看虚函数,类C的中虚函数是怎么分布的?先有一个虚函数表,里面有继承于类A的虚函数和C自己的虚函数(C::aa(), A::aa2(), C::cc()),如果C没有重写aa(),那么第一个虚函数就是A::aa(),接着有第二张虚函数表是继承包含类B的虚函数B::bb()、B::bb2()(类C没有重写B的虚函数)。总的大小就是2张虚表的大小(也即两个虚函数指针的大小)8字节加上3字节的k[3],考虑内存对齐,就是12字节。

虚继承

#include<iostream>
using namespace std;
class A
{
public:
    virtual void aa(){}
private:
    char k[3];
};

class B: virtual public A
{
public:
    //virtual void bb(){}
};

int main()
{
    cout<<"A's size is "<<sizeof(A)<<endl;
    cout<<"B's size is "<<sizeof(B)<<endl;
    return 0;
}

vs和gcc下
执行结果:A's size is 8
              B's size is 12
说明:类B里包含,继承的char k[3],继承的虚函数,类B的虚函数表里有A::aa(),因为是虚继承,还有一个指向父类的指针,该指针为指向虚基类的指针(Pointer to virtual base class)。考虑内存对齐,总大小为12。

#include<iostream>
using namespace std;
class A
{
public:
    virtual void aa(){}
private:
    char k[3];
};

class B: public virtual A
{
public:
    virtual void bb(){}
};

int main()
{
    cout<<"A's size is "<<sizeof(A)<<endl;
    cout<<"B's size is "<<sizeof(B)<<endl;
    return 0;
}

VS执行结果:A's size is 8
                  B's size is 16

gcc执行结果:A's size is 8
                  B's size is 12

说明:对于虚继承,类B虚继承类A时,首先要通过加入一个指针来指向父类A,该指针被称为虚基类指针。然后包含从父类继承过来的3个char,再加上一个虚函数指针。考虑内存对齐,在gcc下结果是4+4+4=12。在VS下,结果是16,why?这一题和上一题区别只是在类B中添加了一个虚函数,但是两个题目中类B都有虚函数表。在VS下调试查看汇编代码,发现多出来的4字节什么也没有。

关于C++虚函数,可以看《C++虚函数表解析》:http://blog.csdn.net/haoel/article/details/1948051

 

作者:阿凡卢

出处:http://www.cnblogs.com/luxiaoxun/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

http://www.cnblogs.com/luxiaoxun/archive/2012/09/01/2666395.html

时间: 2024-08-01 23:03:03

C++类的大小的相关文章

如何查看java一个类的大小

问题描述 如何查看java一个类的大小 就比如我搞了一个类,然后往里边set各种值,我现在想知道这个类的占空间的大小?比如多少KB或者多少MB什么的? 解决方案 如果你知道你的类的路径的话,例如D:aa.txt 那么就 public static void main(String[] args) { FileInputStream fis = null; try { fis = new FileInputStream(new File("D:\aa.txt")); } catch (F

C++空类及没有成员变量的类的大小实例分析_C 语言

众所周知的C++中空类的大小为1,但是除了空类之外的其他一些没有成员变量的类的大小,还是有相当一部分开发人员对此有很多不明之处的. 这里我们以如下代码为例: #include using namespace std; class a {}; class b{}; class c :public a{ virtual void fun() = 0; }; class d :public b, public c{}; int main() { cout << "sizeof(a)&quo

C++空类实例大小不是0原因

python中文件读写的例子 初学者在学习面向对象的程序设计语言时,或多或少的都些疑问,我们写的代码与最终生编译成的代码却 大相径庭,我们并不知道编译器在后台做了什么工作.这些都是由于我们仅停留在语言层的原因,所谓语言层就是教会我们一些基本的语法法则,但不会告诉我们为什么这么做?今天和大家谈的一点感悟就是我在学习编程过程中的一点经验,是编译器这方面的一个具体功能. 首先:我们要知道什么是类的实例化,所谓类的实例化就是在内存中分配一块地址. 那我们先看看一个例子: #include<iostrea

关于虚拟继承类的大小问题探索,VC++ 和 G++ 结果是有区别的

昨天笔试遇到个 关于类占用的空间大小的问题,以前没怎么重视,回来做个试验,还真发现了问题,以后各位笔试考官门,出题时请注明是用什么编译器.        vc6/vc8 cl 和 Dev-C 的g++ 来做的测试: 上代码, 测试代码: #include <stdio.h>class A{public: int x;  int y; A() {  x = 1;     y = 2; }; void go() {  printf("A go()\n"); }    virtu

c++面试常用知识(sizeof计算类的大小,虚拟继承,重载,隐藏,覆盖)

一. sizeof计算结构体 注:本机机器字长为64位 1.最普通的类和普通的继承 #include<iostream> using namespace std; class Parent{ public: void fun(){ cout<<"Parent fun"<<endl; } }; class Child : public Parent{ public: void fun(){ cout<<"Child fun&quo

一个类的实例化对象所占空间的大小

注意不要说类的大小,是类的对象的大小. 首先,类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的.  用sizeof运算符对一个类型名操作,得到的是具有该类型实体的大小.  如果  Class A;  A obj;  那么sizeof(A)==sizeof(obj)  那么sizeof(A)的大小和成员的大小总和是什么关系呢,很简单,一个对象的大小大于等于所有非静态成员大小的总和.  为什么是大于等于而不是正好相等呢?超出的部分主要有以下两方面:  1) C++对象模型本身  对于

Java Math 类中的新功能,第 1 部分: 实数

有时候您会对一个类熟悉到忘记了它的存在.如果您能够写出 java.lang.Foo 的文档, 那么 Eclipse 将帮助您自动完成所需的函数,您无需阅读它的 Javadoc.例如,我使用 java.lang.Math(一个我自认为非常了解的类)时就是这样,但令我吃惊的是,我最近偶然 读到它的 Javadoc -- 这可能是我近五年来第一次读到,我发现这个类的大小 几乎翻了一倍,包含 20 种我从来没听说过的新方法.看来我要对它另眼相看了. Java 语言规范第 5 版向 java.lang.M

【温故而知新】C++中类的大小与其继承关系

[本文参考微信公众号:"程序猿",账号:imkuqin,原文链接] 1.空类: //NullClass.h #pragma once class CNullClass { }; 查看CNullClass实例的大小: int _tmain(int argc, _TCHAR* argv[]) { CNullClass *pNullClass; pNullClass = new CNullClass; printf("size of CNullClass:%d\n",si

C++类对应的内存结构

提示1:对"内存结构"表示有疑问或不解的,先参考: http://blog.csdn.net/guogangj/archive/2007/05/25/1625199.aspx, 本文使用的表示方法和VC6的Memory视图一致,即:左上表示低位.   提示2:下文提到的"类大小"严格上来说是该类经过实例化的对象的大小.当然了,光研究长度的话,两者差别不大,因为:CClassA objA,sizeof(CClassA)和sizeof(objA)得到的结果都是一样的.