类大小计算

首先来个总结,然后下面给出实际例子,实战!

  • 空类的大小为1字节
  • 一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。
  • 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
  • 普通继承,派生类继承了所有基类的函数与成员,要按照字节对齐来计算大小
  • 虚函数继承,不管是单继承还是多继承,都是继承了基类的vptr。(32位操作系统4字节,64位操作系统 8字节)!
  • 虚继承,继承基类的vptr。

1.原则1

  1. /**
  2. * @file blackclass.cpp
  3. * @brief 空类的大小为1字节
  4. * @author 光城
  5. * @version v1
  6. * @date 2019-07-21
  7. */
  8. #include<iostream>
  9. using namespace std;
  10. class A{};
  11. int main()
  12. {
  13. cout<<sizeof(A)<<endl;
  14. return 0;
  15. }

2.原则2

  1. /**
  2. * @file static.cpp
  3. * @brief 静态数据成员
  4. * 静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据成员,一旦被声明,就已经存在。
  5. * @author 光城
  6. * @version v1
  7. * @date 2019-07-21
  8. */
  9. #include<iostream>
  10. using namespace std;
  11. class A
  12. {
  13. public:
  14. char b;
  15. virtual void fun() {};
  16. static int c;
  17. static int d;
  18. static int f;
  19. };
  20. int main()
  21. {
  22. /**
  23. * @brief 16 字节对齐、静态变量不影响类的大小、vptr指针=8
  24. */
  25. cout<<sizeof(A)<<endl;
  26. return 0;
  27. }

3.原则3

  1. /**
  2. * @file morevir.cpp
  3. * @brief 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
  4. * @author 光城
  5. * @version v1
  6. * @date 2019-07-21
  7. */
  8. #include<iostream>
  9. using namespace std;
  10. class A{
  11. virtual void fun();
  12. virtual void fun1();
  13. virtual void fun2();
  14. virtual void fun3();
  15. };
  16. int main()
  17. {
  18. cout<<sizeof(A)<<endl; // 8
  19. return 0;
  20. }

4.原则4与5

  1. /**
  2. * @file geninhe.cpp
  3. * @brief 1.普通单继承,继承就是基类+派生类自身的大小(注意字节对齐)
  4. * 注意:类的数据成员按其声明顺序加入内存,无访问权限无关,只看声明顺序。
  5. * 2.虚单继承,派生类继承基类vptr
  6. * @author 光城
  7. * @version v1
  8. * @date 2019-07-21
  9. */
  10. #include<iostream>
  11. using namespace std;
  12. class A
  13. {
  14. public:
  15. char a;
  16. int b;
  17. };
  18. /**
  19. * @brief 此时B按照顺序:
  20. * char a
  21. * int b
  22. * short a
  23. * long b
  24. * 根据字节对齐4+4=8+8+8=24
  25. */
  26. class B:A
  27. {
  28. public:
  29. short a;
  30. long b;
  31. };
  32. class C
  33. {
  34. A a;
  35. char c;
  36. };
  37. class A1
  38. {
  39. virtual void fun(){}
  40. };
  41. class C1:public A
  42. {
  43. };
  44. int main()
  45. {
  46. cout<<sizeof(A)<<endl; // 8
  47. cout<<sizeof(B)<<endl; // 24
  48. cout<<sizeof(C)<<endl; // 12
  49. /**
  50. * @brief 对于虚单函数继承,派生类也继承了基类的vptr,所以是8字节
  51. */
  52. cout<<sizeof(C1)<<endl; // 8
  53. return 0;
  54. }

5.原则6

  1. /**
  2. * @file virnhe.cpp
  3. * @brief 虚继承
  4. * @author 光城
  5. * @version v1
  6. * @date 2019-07-21
  7. */
  8. #include<iostream>
  9. using namespace std;
  10. class A
  11. {
  12. virtual void fun() {}
  13. };
  14. class B
  15. {
  16. virtual void fun2() {}
  17. };
  18. class C : virtual public A, virtual public B
  19. {
  20. public:
  21. virtual void fun3() {}
  22. };
  23. int main()
  24. {
  25. /**
  26. * @brief 8 8 16 派生类虚继承多个虚函数,会继承所有虚函数的vptr
  27. */
  28. cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C);
  29. return 0;
  30. }