空类,声明时编译器不会生成任何成员函数
对于空类,编译器不会生成任何的成员函数,只会生成1个字节的占位符。
有时可能会以为编译器会为空类生成默认构造函数等,事实上是不会的,编译器只会在需要的时候生成6个成员函数:一个缺省的构造函数、一个拷贝构造函数、一个析构函数、一个赋值运算符、一对取址运算符和一个this指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
   | #include <iostream> using namespace std; class A {   }; class B { 	virtual bool compare(int a,int b) = 0; }; class C:public A,public B {   }; class D:public A,public B { 	virtual bool compare(int a, int b) = 0; }; class E :virtual A, virtual B {   }; class F :virtual A, virtual B { 	virtual bool compare(int a, int b) = 0; }; int main() { 	cout << "A zize:" << sizeof(A) << endl; 	cout << "B zize:" << sizeof(B) << endl; 	cout << "C zize:" << sizeof(C) << endl; 	cout << "D zize:" << sizeof(D) << endl; 	cout << "E zize:" << sizeof(E) << endl; 	cout << "F zize:" << sizeof(F) << endl; 	system("pause"); 	return 0; }
   | 
 
分析:
类A是空类,但空类同样可以被实例化,而每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以sizeof(A)的大小为1。
类B里面因有一个纯虚函数,故有一个指向虚函数的指针(vptr),32位系统分配给指针的大小为4个字节,所以sizeof(B)的大小为4。类C继承于A和B,编译器取消A的占位符,保留一虚函数表,故大小为4。类D继承于A和B,派生类基类共享一个虚表,故大小为4。类E虚继承A和B,含有一个指向基类的指针(vftr)和一个指向虚函数的指针。类F虚继承A和B,含有一个指向基类的指针(vftr)和一个指向虚函数的指针。
空类,定义时会生成6个成员函
等价于:
1 2 3 4 5 6 7 8 9 10
   | class Empty {   public:     Empty();                                 Empty(const Empty &rhs);                 ~Empty();                                Empty& operator=(const Empty &rhs);      Empty* operator&();                      const Empty* operator&() const;      };
   | 
 
使用时的调用情况:
1 2 3 4 5 6 7 8
   |  Empty *e = new Empty();     delete e;                   Empty e1;                   Empty e2(e1);               e2 = e1;                    Empty *pe1 = &e1;           const Empty *pe2 = &e2;    
 
  | 
 
C++编译器对这些函数的实现:
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   |  inline Empty::Empty()                           { } inline Empty::~Empty()                          { } inline Empty *Empty::operator&()                {   return this;  }            inline const Empty *Empty::operator&() const     {   return this; } inline Empty::Empty(const Empty &rhs)            {       }   inline Empty& Empty::operator=(const Empty &rhs)  {       }
 
  |