sizeof 类

虚继承的话,在子类末尾要多一份指向基类的指针;只保留一份,多的要减去

如果子类重新定义了虚函数,那么它不放在基类的虚表里面,而是单独重新开一份虚表,这个和非虚继承是不同的


----------------------------------------------------

1.class K

{

 

};

sizeof(K) = 1;//空类大小为1

 

2. class A

{

  int a;

  void a();

};

sizeof(A) = 4;//不计算成员函数的空间

 

3. class B

{

   int b;

   virtual void b();

 }

 sizeof(B) = 4+4;//有虚函数,添加虚表指针大小

 

4. class C:virtual public B

{

   int c;

   virtual void c();

};

sizeof(C)=4+4+4+4+4;//虚继承,添加指向基类的指针;虚继承中重新定义了虚函数,则新添加一个虚表指针

 

5. class D:virtual public B

{

   int d;

   virtual void d();

}

sizeof(D)=4+4+4+4+4;

 

6. class E:public C,public D

{

  int e;

}

sizeof(E) = 4+2*(4+4+4+4+4)-4;//只保留一份指向原始基类的指针所以要减4

 

总结:sizeof 类 = 成员变量+虚函数指针。sizeof 继承类 = 本身成员变量+父类的大小,如果是虚拟继成的话,则另外加一个指向父类指针的大小;当多重继承的时候,如例6中,所示,这时候只需要,保留一份指向虚基类B的指针,所以得减掉一个指针的大小。



------------------------------------

类的内存布局-sizeof(类对象)

一、简单对象
#include<iostream.h>
class A
{
public:

int a;

char b;

static int c;

virtual ~A(){};

};

int A::c=123;


int main()
{

A asimple;

cout<<sizeof(asimple)<<endl;

return 0;

//result=4+4+1+3=12即字节对齐(虚指针+非静态数据成员)

二、单继承

#include<iostream.h>
class A
{
public:

int a;

char b;

static int c;

virtual ~A(){};

};

int A::c=123;

class B:public A
{
public:

int d;

virtual void foob(){};

};

int main()
{

// A asimple;

B bsimple;

cout<<sizeof(bsimple)<<endl;

return 0;

//result=(4+4+1+3)+4=16即字节对齐(基类size+B自己的非静态数据成员)

三、多继承

#include<iostream.h>
class A
{
public:

int a;

char b;

static int c;

virtual ~A(){};

};

int A::c=123;

class B
{
public:

int d;

virtual void foob(){};

};
class C:public A,public B
{
public:

int e;

};


int main()
{

A asimple;

B bsimple;

C csimple;

cout<<sizeof(asimple)<<endl; //12

cout<<sizeof(bsimple)<<endl; //8

cout<<sizeof(csimple)<<endl;

//12+8+4=24 即字节对齐(基类A大小+基类B大小+C自己的非静态数据成员)

return 0;

}

四、菱形继承
1.非虚拟继承方式

#include<iostream.h>
class A
{
public:

int a;

char b;

static int c;

virtual ~A(){};

virtual void fooa(){};

};

int A::c=123;

class B:public A
{
public:

int d;

virtual void foob(){};

};
class C:public A
{
public:

int e;

};

class D:public B,public C
{
public:

char f;

};


int main()
{

A asimple;

B bsimple;

C csimple;

D dsimple;

cout<<sizeof(asimple)<<endl;//12

cout<<sizeof(bsimple)<<endl;//16

cout<<sizeof(csimple)<<endl;//16

cout<<sizeof(dsimple)<<endl;//16+16+4=36 同多继承方式

return 0;


2.虚拟继承
(1)B中重写fooa(),但不定义新的虚函数
#include<iostream.h>
class A
{
public:

int a;

char b;

static int c;

virtual ~A(){};

virtual void fooa(){};

};

int A::c=123;

class B:virtual public A
{
public:

int d;

// virtual void foob(){};

virtual void fooa(){cout<<"fooa in B"<<endl;};

};
class C:virtual public A
{
public:

int e;

};

class D:public B,public C
{
public:

char f;

};


int main()
{

A asimple;

B bsimple;

C csimple;

D dsimple;

cout<<sizeof(asimple)<<endl;//12

cout<<sizeof(bsimple)<<endl;//20

cout<<sizeof(csimple)<<endl;//20

cout<<sizeof(dsimple)<<endl;//32

return 0;

}

(2)B定义新的虚函数
#include<iostream.h>
class A
{
public:

int a;

char b;

static int c;

virtual ~A(){};

virtual void fooa(){};

};

int A::c=123;

class B:virtual public A
{
public:

int d;

virtual void foob(){cout<<"foob in B"<<endl;};

// virtual void fooa(){cout<<"fooa in B"<<endl;};

};
class C:virtual public A
{
public:

int e;

};

class D:public B,public C
{
public:

char f;

};


int main()
{

A asimple;

B bsimple;

C csimple;

D dsimple;

cout<<sizeof(asimple)<<endl;//12

cout<<sizeof(bsimple)<<endl;//24

cout<<sizeof(csimple)<<endl;//20

cout<<sizeof(dsimple)<<endl;//36

return 0;

}

综合1,2,可见
1.非虚拟继承时,无论派生类是否定义新的虚函数,基类和派生类总是共享一个虚函数表,不需要另加指向虚函数的指针。
2.虚拟继承时,若是派生类只是继承或重写基类中虚函数,则基类和派生类是共享一个虚函数表;若派生类新定义了虚函数,则需要新加一个虚指针指向新的虚函数表。


### sizeof 的定义与用途 `sizeof` 是一种运算符,在多种编程语言中用于获取数据型的大小(以字节为单位)。它通常被用来计算变量、数组或其他数据结构所占用的内存空间。 #### 在 C/C++ 中 `sizeof` 的基本用法 在 C 和 C++ 编程语言中,`sizeof` 运算符返回指定型或对象所需的存储量。其语法如下: ```cpp size_t size = sizeof(type); ``` 或者对于已声明的对象: ```cpp size_t size = sizeof(object); ``` 这里的关键点在于,`sizeof` 返回的是编译期常量,因此它的值是在程序运行之前就确定下来的[^2]。 #### 示例代码展示 `sizeof` 使用方法 下面是一个简单的例子,展示了如何使用 `sizeof` 来测量不同型的数据所需的空间: ```cpp #include <iostream> int main() { int integerVariable; double floatingPointVariable; std::cout << "Size of an integer: " << sizeof(integerVariable) << " bytes\n"; std::cout << "Size of a double precision float: " << sizeof(floatingPointVariable) << " bytes\n"; // 测量自定义结构体的大小 struct ExampleStruct { char c; long l; }; std::cout << "Size of the structure 'ExampleStruct': " << sizeof(ExampleStruct) << " bytes\n"; return 0; } ``` 这段代码演示了不同数据型以及复杂结构体的尺寸测量方式[^2]。 #### Java 中实现似的 `sizeof` 功能 尽管 Java 并未提供内置的 `sizeof` 关键词,但可以通过第三方库或手动估算的方式来模拟这一功能。由于 JVM 对象的实际内存消耗可能受到垃圾回收机制的影响而变化不定,精确计算并非易事。然而,可以借助一些工具完成近似估计。 以下是通过反射技术粗略统计实例字段总和的一个简单版本: ```java import java.lang.reflect.Field; import java.util.ArrayList; public class SizeOf { public static void main(String[] args) throws IllegalAccessException { ArrayList<Integer> list = new ArrayList<>(); for (int i=0;i<1000;i++) { list.add(i); } System.out.println("Estimated memory usage by List: "+getSize(list)+" bytes"); } @SuppressWarnings("rawtypes") public static long getSize(Object o) throws IllegalAccessException { Class clazz = o.getClass(); Field[] fields = clazz.getDeclaredFields(); long totalSize = 0L; for(Field field : fields){ field.setAccessible(true); if(field.getType().isPrimitive()){ switch (field.getName()) { case "boolean": totalSize += 1; break; case "byte": totalSize += 1; break; case "char": totalSize += 2; break; case "short": totalSize += 2; break; case "int": totalSize += 4; break; case "long": totalSize += 8; break; case "float": totalSize += 4; break; case "double": totalSize += 8; break; } }else{ Object objValue = field.get(o); if(objValue != null && !objValue.getClass().getName().startsWith("java")){ totalSize += getSize(objValue); } } } return totalSize; } } ``` 注意该算法仅适用于特定场景下的简化模型,并不完全反映真实情况[^1]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值