类的内存变化(函数和虚函数,继承和虚继承)

目录

1.空类大小

2.类的大小

3.类的继承大小

4.虚继承多个类大小

总结:


1.空类大小

        空类的内存占1个字节,因为空类也可能会实例化,为了能分配有唯一的内存地址,而自动给它添加1个字节的大小

2.类的大小

        类的大小是类中成员变量的大小,成员函数不分配空间(静态成员的是在堆中的,不属于类内,有虚函数的类会生成一个虚表指针)

class A
{
};
class B
{
	char a[3];
	int b;
};
class C 
{
	void aa() { cout << 111; };
};
class D
{
	virtual void cc();
};

int main()
{
	cout << sizeof(A) << endl; // 1
	cout << sizeof(B) << endl; // 8 【内存对齐,char(3+1)+int(4)】
	cout << sizeof(C) << endl; // 1 【成员函数内存为0】
	cout << sizeof(D) << endl; // 8 【有虚函数的类中会且只会生成一个虚函数指针】
	return 0;
}

3.类的继承大小

        一般的继承(共享虚表指针)

                        子类的大小 = 父类的大小 + 自身的大小 + 虚表指针

        虚继承 (不共享虚表指针,并且多了个虚基类指针)

                        子类的大小 = 父类的大小(包含虚表指针) + 自身的大小(包含虚表指针) +虚基类指针

class A
{
};
class B 
{
	char a[3];
	int b;
};
class C 
{
	void aa() { cout << 111; };
};
class D
{
	virtual void cc() {};
};


class E1 :public B //普通继承B
{
};
class E2 :public virtual B //虚继承B
{
};
class G1 :public D //普通继承D
{
};
class G2 :public virtual D //虚继承D
{
};

class F1 :public D //普通继承D
{
	virtual void aa() {};
};
class F2 :public virtual D //虚继承D
{
	virtual void aa() {};
};

//多级继承
class Q1 : public F1
{
	virtual void q1() {};
};
class Q2 : public virtual F1
{
	virtual void q1() {};
};

class W1 : public F2
{
	virtual void q1() {};
};
class W2 : public virtual F2
{
	virtual void q1() {};
};



int main()
{
	cout << "E1(pubilc B)   " << sizeof(E1) << endl; //8【B(8)+E1(0)】
	cout << "E2(virtual B)   " << sizeof(E2) << endl; //16【B(8)+E2(0)+虚基类指针(8)】

	cout << "G1(pubilc D)   " << sizeof(G1) << endl; //8【D(8)+G1(0)】
	cout << "G2(virtual D)   " << sizeof(G2) << endl; //16【D(8)+G2(0)+虚基类指针(8)】

	cout << "F1(pubilc D)   " << sizeof(F1) << endl; //8【共享一个虚表指针】
	cout << "F2(virtual D)   " << sizeof(F2) << endl; //24【D(8)+F2(8)+虚基类指针(8)】(虚继承时,虚表指针不共享)

	cout << "Q1(public F1)   " << sizeof(Q1) << endl; //8【共享一个虚表指针】
	cout << "Q2(virtual F1)   " << sizeof(Q2) << endl; //24【多了1个虚基类指针和1个自身的虚表指针】

	cout << "W1(public F2)   " << sizeof(W1) << endl; //24【普通继承和父类共享同一个虚表指针】
	cout << "W2(virtual F2)   " << sizeof(W2) << endl; //40【多1个虚基类指针和1个虚表指针】

	return 0;

4.虚继承多个类大小

class A { int a; };
class B { int b; };
class C { int c; };
class D { int d; };
class E :virtual A, virtual B, virtual C
{};

int main()
{
	cout << sizeof(E);//24【A(4)+B(4)+C(4)+D(4)+虚基类指针(8)】
	return 0;
}

总结

1.在普通继承中,子类和父类共享同一个虚表指针:

        子类的大小 = 父类变量成员大小 + 自身变量成员大小 + 共享的虚表指针;

2.在虚继承中,子类和父类不共享虚函数指针(父类和子类各有一个虚表指针),并且还多了一个虚基类指针

        子类的大小 = 父类变量成员大小 + 自身变量成员大小 + 父类的虚表指针 +子类的虚表指针+虚基类指针;

3.虚继承生成的虚基类指针是不共享的,虚继承几次就有几个虚基类指针,在同一个类中虚继承多个父类也只有一个虚基类指针;

虚函数指针、虚表指针、虚函数表的区别(个人理解)

1.虚函数指针是在有虚函数的类实例化对象时,编译器会在该类对象中生成并初始化一个指向虚函函数的指针

2.虚表指针是指向虚表的指针,在类中有虚函数的时候,编译器会在类的构造函数生成并初始化虚表指针

3.虚表是在编译过程中生成的一个储存虚函数地址的指针数组;

        虚表指针是类的属性,虚函数指针是对象的属性

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值