1. 普通类对象是什么布局?
struct Base {
Base() = default;
~Base() = default;
void Func() {}
int a;
int b;
};
int main() {
Base a;
return 0;
}
2. 带虚函数的类对象是什么布局?
struct Base {
Base() = default;
virtual ~Base() = default;
void FuncA() {}
virtual void FuncB() {
printf("FuncB\n");
}
int a;
int b;
};
int main() {
Base a;
return 0;
}
这个含有虚函数的结构体大小为16,在对象的头部,前8个字节是虚函数表的指针,指向虚函数的相应函数指针地址,a占4个字节,b占4个字节,总大小为16。
offset_to_top(0)
:表示当前这个虚函数表地址距离对象顶部地址的偏移量,因为对象的头部就是虚函数表的指针,所以偏移量为0。
RTTI指针:指向存储运行时类型信息(type_info)的地址,用于运行时类型识别,用于typeid和dynamic_cast
。
3. 单继承下不含有覆盖函数的类对象是什么布局?
struct Base {
Base() = default;
virtual ~Base() = default;
void FuncA() {}
virtual void FuncB() {
printf("Base FuncB\n");
}
int a;
int b;
};
struct Derive : public Base{
public:
int c;
};
int main() {
Base a;
Derive d;
return 0;
}
这里的FuncB函数,还是Base类中的FuncB,因为在子类中没有重写这个函数,那么如果子类重写这个函数后对象布局是什么样的,请继续往下看。
4. 单继承下含有覆盖函数的类对象是什么布局?
struct Base {
Base() = default;
virtual ~Base() = default;
void FuncA() {}
virtual void FuncB() {
printf("Base FuncB\n");
}
int a;
int b;
};
struct Derive : public Base{
void FuncB() override {
printf("Derive FuncB \n");
}
int c;
};
int main() {
Base a;
Derive d;
return 0;
}
注意这里虚函数表中的FuncB函数已经是Derive中的FuncB啦,因为在子类中重写了父类的这个函数。
再注意这里的RTTI中有了两项,表示Base和Derive的虚表地址是相同的,Base类里的虚函数和Derive类里的虚函数都在这个链条下。
5. 多继承下不含有覆盖函数的类对象是什么布局?
struct BaseA {
BaseA() = default;
virtual ~BaseA() = default;
void FuncA() {}
virtual void FuncB() {
printf("BaseA FuncB\n");
}
int a;
int b;
};
struct BaseB {
BaseB() = default;
virtual ~BaseB() = default;
void FuncA() {}
virtual void FuncC() {
printf("BaseB FuncC\n");
}
int c;
int d;
};
struct Derive : public BaseA, public BaseB{
};
int main() {
BaseA a;
Derive d;
return 0;
}
offset_to_top(0)
:表示当前这个虚函数表(BaseA,Derive)地址距离对象顶部地址的偏移量,因为对象的头部就是虚函数表的指针,所以偏移量为0。
再注意这里的RTTI中有了两项,表示BaseA和Derive的虚表地址是相同的,BaseA类里的虚函数和Derive类里的虚函数都在这个链条下,截至到offset_to_top(-16)
之前都是BaseA和Derive的虚函数表。
offset_to_top(-16)
:表示当前这个虚函数表(BaseB)地址距离对象顶部地址的偏移量,因为对象的头部就是虚函数表的指针,所以偏移量为-16,这里用于this指针偏移,下一小节会介绍。
注意下后面的这个RTTI:只有一项,表示BaseB的虚函数表,后面也有两个虚析构函数。
6. 多继承下含有覆盖函数的类对象的是什么布局?
struct BaseA {
BaseA() = default;
virtual ~BaseA() = default;
void FuncA() {}
virtual void FuncB() {
printf("BaseA FuncB\n");
}
int a;
int b;
};
struct BaseB {
BaseB() = default;
virtual ~BaseB() = default;
void FuncA() {}
virtual void FuncC() {
printf("BaseB FuncC\n");
}
int c;
int d;
};
struct Derive : public BaseA, public BaseB{
void FuncB() override {
printf("Derive FuncB \n");
}
void FuncC() override {
printf("Derive FuncC \n");
}
};
int main() {
BaseA a;
Derive d;
return 0;
}
7. 多继承中不同的继承顺序产生的类对象布局相同吗?
struct BaseA {
BaseA() = default;
virtual ~BaseA() = default;
void FuncA() {}
virtual void FuncB() {
printf("BaseA FuncB\n");
}
int a;
int b;
};
struct BaseB {
BaseB() = default;
virtual ~BaseB() = default;
void FuncA() {}
virtual void FuncC() {
printf("BaseB FuncC\n");
}
int c;
int d;
};
struct Derive : public BaseB, public BaseA{
void FuncB() override {
printf("Derive FuncB \n");
}
void FuncC() override {
printf("Derive FuncC \n");
}
};
int main() {
BaseA a;
Derive d;
return 0;
}
BaseB的虚函数表指针和数据在上面,BaseA的虚函数表指针和数据在下面,以A,B的顺序继承,对象的布局就是A在上B在下,以B,A的顺序继承,对象的布局就是B在上A在下。
标签:BaseA,Derive,FuncB,对象,模型,C++,int,Base,void From: https://www.cnblogs.com/love-9/p/18087157