空类,声明时编译器不会生成任何成员函数
对于空类,编译器不会生成任何的成员函数,只会生成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) { }
|