C式继承
什么时候会产生虚表和指向虚表的指针?
#include <iostream>
using namespace std;
class A{};
class B : public A {};
int main() {
cout << sizeof(A) << endl;//1 char
cout << sizeof(B) << endl;//1 char
return 0;
}
输出:
1
1
请按任意键继续. . .
可以看出普通继承在没有虚函数和虚继承的时候,并不会产生虚表和虚指针。
虚函数产生虚表和虚指针
只要一个类有虚函数,为了实现虚函数就要通过虚表和虚表指针
#include <iostream>
using namespace std;
class A
{
virtual ~A(){}
};
class B
{
virtual void f() {}
};
int main() {
cout << sizeof(A) << endl;//1 vptr
cout << sizeof(B) << endl;//1 vptr
return 0;
}
输出:
4
4
请按任意键继续. . .
虚表指针是谁设置的?
是构造函数设置的。
默认构造函数是不是一定会创建?
并不是,只有涉及到虚函数设置虚表的时候编译器才一定会产生构造函数;
同理,因为要设置虚表指针所以拷贝构造函数也会被编译器生成出来;
此时memcpy是危险的,不可取的,因为会复制错误的虚表指针。
对于C那种struct纯基本类型的数据成员结构体是不会产生构造函数的。
Data语义学
class X { };
class Y : public virtual X { };
class Z : public virtual X { };
class A : public Y, public Z { };
类型 | 编译器A | Visual C++ |
X | 1 = sizeof(X) 1byte char安插用以在内存中区分两个object | 1 = sizeof(X) 1byte char安插用以在内存中区分两个object |
Y | 8 = sizeof(Y) 8 = char + vptr 8 = (1 + 3(内存对齐)) + 4 | 4 = sizeof(Y) 4 = vptr (不再需要额外的1 byte char) |
Z | 8 = sizeof(Y) 8 = char + vptr 8 = (1 + 3(内存对齐)) + 4 | 4 = sizeof(Y) 4 = vptr (不再需要额外的1 byte char) |
A | 12 = sizeof(A) 12 = char + vptr1 + vptr2 12 = (1 + 3(内存对齐)) + 4 + 4 | 8 = sizeof(A) 8 = vptr1 + vptr2 8 = 4 + 4 (不再需要额外的1 byte char) |
编译器A Visual C++
字节对齐
#include <iostream>
using namespace std;
class A
{
char a;
};
class B : public A
{
char b;
};
class C : public B
{
char c;
};
int main() {
cout << sizeof(A) << endl;//1 char
cout << sizeof(B) << endl;//2 char
cout << sizeof(C) << endl;//3 char
return 0;
}
输出:
1
2
3
请按任意键继续. . .
再来看看字节对齐之后,A中增加一个int i
#include <iostream>
using namespace std;
class A
{
int i;
char a;
};
class B : public A
{
char b;
};
class C : public B
{
char c;
};
int main() {
cout << sizeof(A) << endl;//2 int
cout << sizeof(B) << endl;//3 int
cout << sizeof(C) << endl;//4 int
return 0;
}
输出:
8
12
16
请按任意键继续. . .