目录
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.虚表是在编译过程中生成的一个储存虚函数地址的指针数组;
虚表指针是类的属性,虚函数指针是对象的属性