C++中类的大小

前面我们提到过C中的struct结构体的大小,什么内存对齐,偏移量,然后Linux和Window下的还不一样,

搞懂了上面的这些,那就明白了C++中的了吗??

这里的结构体可是还有函数的,还有虚函数,友员函数,继承,多重继承,虚继承,等等一大堆东西,那这里面又是咋样的呢??


1,class空类

     C++的空类是指这个类不带任何数据,即类中没有非静态数据成员变量,没有虚函数,也没有虚基类,也就是说:空类对象不使用任何空间,因为没有任何对象需要存储,但是,但是,但是,:C++标准规定,凡是一个对立的对象都必须具有非零大小:::::

所以,也就是说:空类或者空类的对象的大小也不为0。。。

#include <iostream>                                                             
using namespace std;

class test
{
};

int main()
{
        cout<<sizeof(test)<<endl;
        return 0;
}
运行结果:

所以我们可以看到空类test的大小为1

其实在C++早起的编译器中,这个值为0(也就是说空类的大小),然而当我们创建这样的对象是,它与紧接着后面的对象有相同的地址:

test  tt;

int    a;(这里tt和变量a有相同的地址),这样的话我们对对象tt的操作就会直接影响a,所以对与如今的编译器来说,空类的大小为1、

类的实例化就是在内存中分配一块地址,每一个实例在内存中都是独一无二的地址。所以空类实例化后也就有了自己独一无二的地址了


2,当含有虚成员函数时:

#include <iostream>
using namespace std;


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


int main()
{
	cout<<sizeof(A)<<endl;
	return 0;
} 

运行结果(window,dev-c++):

C++中类的大小_第1张图片

此时,类的大小为4,因为在类中隐藏了一个指针,该指针指向虚函数表(具有虚函数表的地址),正是因为如此,使得C++能够支持多态,即在运行时绑定函数的地址。

运行结果(Linux):

所以可以看出,虚函数在linux系统里面占了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 is size:"<<sizeof(A)<<endl;
	cout<<"B is size:"<<sizeof(B)<<endl;
	
	return 0;
}

Linux中给出的结果是:

16,16

window中(vc,dev-c++)

8,8

说明:有虚函数的类有个virtual table(虚函数表),里面包含了类的所有虚函数,类中有个virtual table pointers,通常是:vptr指向这个virtual table,占有4个字节,成员类B   public继承于A,类B的虚函数表里实际上有两个虚函数

A::aa()和B::bb()都在虚表里面,虚表的每一个表项保存着一个虚函数的入口地址。当调用虚函数时,我们是先找到虚表中的表项,找到入口地址再执行。

然而对于含有虚函数的类的大小而言,大小等于成员变量+指向虚表的指针

类B的大小等于char  k【3】的大小加上一个指向虚函数表指针vptr的大小,并且还必须考虑内存对齐,故结果为:8


所以,觉得应该是在linux下:在类中涉及到虚函数的指针(指向虚表的指针+指向父类的指针)都应该占用8个字节,下面的程序都可以这样理解!!!


#include <iostream>
using namespace std;

class A
{
	public:
		virtual void aa()
		{
		}
	private:
		char k[3];
};

class B:public A
{
};

int main()
{
	cout<<"A is size:"<<sizeof(A)<<endl;
	cout<<"B is size:"<<sizeof(B)<<endl;
	
	return 0;
}
window下(vc和dev-c++):

A is size:8

B is size:8

linux下:

A is size:16

B is size:16

类B看上去没有虚函数,实际上类B也是有的,它是通过继承A来的,所以说,类A和类B的虚函数表里面都是A::aa()



#include <iostream>
using namespace std;

class A
{
public:
	virtual void aa()
	{}
	virtual void aa1()
	{}
private:
	char k[3];
};

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

int main()
{
	cout<<"A is size:"<<sizeof(A)<<endl;
	cout<<"B is size:"<<sizeof(B)<<endl;

	return 0;
}

window下(vc和dev-c++)

A is size:8

B is size:8

linux下:

A is size:16

B is size:16

可以看出:一个类中若存在多个虚函数,无论有多少个虚函数都只是存在一个指向虚表的指针,虚表的每一个表项保存着一个虚函数的入口地址。当调用虚函数时,我们是先找到虚表中它对应的入口地址,找到入口地址再执行。

对于上面这种情况:

类A的虚表中存在的是:A:aa() ,A:aa1()

类B的虚表中存在的是:A:aa() ,A:aa1(),B:bb(),B:bb1()           





#include <iostream>
using namespace std;

class A
{
public:
	virtual void aa()
	{}
	virtual void aa1()
	{}
private:
	char k[3];
};

class B
{
	virtual void bb()
	{}
	virtual void bb1()
	{}
};


class C:public A,public B
{
public:
	virtual void aa(){}        //重写虚函数
	virtual void cc()
	{}
};


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

window下(vc和linux)

A is size:8

B is size:4

C is size:12

linux下:

A is size:16

B is size:8

C is size:24

类A和B的大小就不用解释了,参照上面我们所讲的,类C(有虚函数的覆盖)多重继承于A和B

首先我们来看成员变量,有一个继承A的char[3].

在来看虚函数,那么类C中的虚函数是如何分布的,它可是继承了两个基类啊!!!(有两个虚函数表)

1,第一个虚函数表,继承于类A的虚函数和C自己的虚函数(C::aa(),A::aa2(),C::cc()),当然如果我们没有重写虚函数的话,那么第一个虚函数表就是:(A::aa(),A::aa2(),C::cc())

2,第二个虚函数表,继承于类B的虚函数和C自己的虚函数(B::bb(),B::bb2(),C::aa(),C::cc())嗯嗯,应该就是这样了

所以说:总的大小就是指向两张虚表的大小在加上继承过来的成员变量,加上内存对齐的因素就是12字节


#include <iostream>
using namespace std;

class A
{
public:
	virtual void aa()
	{}
private:
	char k[3];
};

class B:virtual public A
{

};

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

window下(vc和linux)

A  is  size:8

B  is  size:12

linux下:

A is size:16

B is size:24


类B里包含继承过来的char k【3】,继承的虚函数

类B的虚函数表里有A::aa(),所以有一个指向虚表的指针,又因为是虚继承,所以还有一个指向父类的指针,加上成员变量,考虑内存对齐,所以总大小为12


友元函数:

#include <iostream>
using namespace std;

class A
{
public:
	friend void kk();
};

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

运行结果:

A  is  size  :1

所以我们可以知道友元函数如同其他函数就是一样的,也是不影响类的大小,如上,类A也相当于空类!


#include <iostream>
using namespace std;

class A
{
public:
	static int a;
};

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

运行结果:

A is size :1

所以此刻A类还是空类!!!

空类是指这个类不带任何数据,即类中没有非静态数据成员变量,没有虚函数,也没有虚基类,也没有函数(包括友元函数)


本文关于虚函数的类的介绍:

摘自(谢谢啦):http://www.cnblogs.com/luxiaoxun/archive/2012/09/01/2666395.html

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

你可能感兴趣的:(C++中类的大小)