深入分析C++中类的大小_C 语言

首先看一个例子:

复制代码 代码如下:

#include <iostream>
 using namespace std;

 class A{};

 class B
 {
     int b;
     char c;
 };

 class C
 {
     int c1;   
     static int c2;
 };
 int C::c2 = 1;

 class D:public C,public B{
     int d;
 };
 int main()
 {
     cout<<"sizeof(A)="<<sizeof(A)<<endl;
     cout<<"sizeof(B)="<<sizeof(B)<<endl;
     cout<<"sizeof(C)="<<sizeof(C)<<endl;
     cout<<"sizeof(D)="<<sizeof(D)<<endl;

     return 0;
 }

运行结果为:

sizeof(A)=1

sizeof(B)=8

sizeof(C)=4

sizeof(D)=16

对于类A来说,虽然A是一个空类,但为了便于空类进行实例化,编译器往往会给它分配一个字节,这样A实例化后便在内存中有了一个独一无二的地址.对于类B,B的大小应为sizeof(int)+sizeof(char)=5,但是考虑内存对齐,B的大小应为8.对于类C,类的静态成员变量被放在全局区,和类的普通成员并没有放在一块。类的静态成员被声明后就已存在,而非静态成员只有类被实例化后才存在。所以C的大小为sizeof(int)=4。D的大小为B+C的大小+自身数据成员的大小,一共为16.

 

==========================分割线在这里====================================

下面讨论含有虚函数的类的大小:

复制代码 代码如下:

#include <iostream>
 using namespace std;

 class A
 {
 public:
     void virtual aa(){};
 };

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

 class C:virtual A
 {
 public:
     void virtual aa(){};
     void cc(){};
 };

 class D:virtual A
 {
 public:
     void virtual dd(){};
 };

 int main()
 {
     cout<<"sizeof(A)="<<sizeof(A)<<endl;
     cout<<"sizeof(B)="<<sizeof(B)<<endl;
     cout<<"sizeof(C)="<<sizeof(C)<<endl;
     cout<<"sizeof(D)="<<sizeof(D)<<endl;

     return 0;
 }

运行结果为:

sizeof(A)=4

sizeof(B)=4

sizeof(C)=8

sizeof(D)=12

对于class A,它含有一个虚函数,编译器会为虚函数生成一张虚函数表,来记录对应的函数地址,为此,在class A的内存地址中要有一个vfptr_A指针指向这个虚表,所以class A的大小为指针大小,即4.(注意,无论类中有多少个虚函数,它们的大小都是4,因为内存中只需要保存这个指针即可)。

对于class B,它是public继承A,虽然它也有一个虚函数,但是从结果看,B应该和A都在B的vtable(虚表中),所以class B的大小为4.

对于class C,它是vitual 继承A,所以要有一个指向父类A的指针,占有4字节大小aa()是继承自class A的虚函数,从结果来看,它没有在内存中占有空间,所以C的大小为sizeof(A)+4=8.

对于class D,它是虚继承class A,同上,要有一个指向父类A的指针,同时,class D中有虚函数,所以要有一个指向虚表的指针,所以sizeof(D)=sizeof(A)+4+4=12

时间: 2024-09-26 07:56:10

深入分析C++中类的大小_C 语言的相关文章

深入解析C++中类的多重继承_C 语言

C++类的多继承 在前面的例子中,派生类都只有一个基类,称为单继承.除此之外,C++也支持多继承,即一个派生类可以有两个或多个基类. 多继承容易让代码逻辑复杂.思路混乱,一直备受争议,中小型项目中较少使用,后来的 Java.C#.PHP 等干脆取消了多继承.想快速学习C++的读者可以不必细读. 多继承的语法也很简单,将多个基类用逗号隔开即可.例如已声明了类A.类B和类C,那么可以这样来声明派生类D: class D: public A, private B, protected C{ //类D新

用C语言获取文件的大小示例分享_C 语言

查了一下发现同C语言的文件操作函数便可以很容易的实现这样的功能.在自己实现的函数中使用到的函数就只有fseek和ftell.它们的说明如下: fseek 语法: #include <stdio.h> int fseek( FILE *stream, long offset, int origin ); 函数fseek()为给出的流设置位置数据. origin的值应该是下列值其中之一(在stdio.h中定义): 名称 说明 SEEK_SET 从文件的开始处开始搜索 SEEK_CUR 从当前位置开

排列和组合算法的实现方法_C语言经典案例_C 语言

排列和组合算法是考查递归的常见算法,这两种算法能用递归简洁地实现. 本人在经过多次摸索和思考之后,总结如下,以供参考. 程序代码如下: #include <stdio.h> #include <stdlib.h> char array[] = "abcd"; #define N 4 #define M 3 int queue[N] = {0}; int top = 0; int flag[N] = {0}; void perm(int s, int n) { i

C++开发:为什么多线程读写shared_ptr要加锁的详细介绍_C 语言

我在<Linux 多线程服务端编程:使用 muduo C++ 网络库>第 1.9 节"再论 shared_ptr 的线程安全"中写道: (shared_ptr)的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化.根据文档(http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#ThreadSafety), shared_ptr 的线程

c++ 虚函数与纯虚函数的区别(深入分析)_C 语言

在面向对象的C++语言中,虚函数(virtual function)是一个非常重要的概念.因为它充分体现 了面向对象思想中的继承和多态性这两大特性,在C++语言里应用极广.比如在微软的MFC类库中,你会发现很多函数都有virtual关键字,也就是说, 它们都是虚函数.难怪有人甚至称虚函数是C++语言的精髓. 那么,什么是虚函数呢,我们先来看看微软的解释: 虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本. 这个定

C语言字符串大小比较_C 语言

C语言字符串大小比较 #include <stdio.h> #include <string.h> int fun(char *a,char *b) { int i = 0,j = 0; while(a[i]&&b[j]) { if(a[i]-b[j]>0) return 1; else if(a[i]-b[j]<0) return -1; i++,j++; } if(strlen(a)==i&&strlen(b)==j) return

浅谈MFC 改变控件大小和位置_C 语言

用CWnd类的函数MoveWindow()或SetWindowPos()可以改变控件的大小和位置. void MoveWindow(int x,int y,int nWidth,int nHeight); void MoveWindow(LPCRECT lpRect); 第一种用法需给出控件新的坐标和宽度.高度: 第二种用法给出存放位置的CRect对象: 例: CWnd *pWnd; pWnd = GetDlgItem( IDC_EDIT1 ); //获取控件指针,IDC_EDIT1为控件ID号

C语言指针的长度和类型深入分析_C 语言

指针是C语言的精髓,本文就以实例的形式详细分析了C语言的长度和类型.对于初学者深入理解C语言程序设计有很好的参考价值.具体分析如下: 一般来说,如果考虑应用程序的兼容性和可移植性,指针的长度就是一个问题,在大部分现代平台上,数据指针的长度通常是一样的,与指针类型无关,尽管C标准没有规定所有类型指针的长度相同,但是通常实际情况就是这样.但是函数指针长度可能与数据指针的长度不同. 指针的长度取决于使用的机器和编译器,例如:在现代windows上,指针是32位或是64位长 测试代码如下: #inclu

节序问题:解析大小的端判定_C 语言

大小端的判断很简单,可判断了有什么用呢?这是一个难缠的问题,我最近就碰到了这样一个问题,比如,int a = 0x12345678,char* p = &a,那么p[0]等于多少呢?答案要么是0x12,要么是0x78,对吧,如果你知道他是小端(因为地球人都知道),那么你肯定就知道p[0] = 0x78,呵呵,换句话说,理解大小端对指针的运用还是有一定帮助的. 一.大小端概念要判断电脑的大小端,肯定先要理解大小端的概念:大端模式(Big-Endian),是指数据的高位,保存在内存的低地址中,而数据