当 base 具有虚函数时,静态转换为 base class 会产生意外结果
Static cast to base class gives unexpected results when base has a virtual function
struct Base1{
int b1[100];
};
struct Base2{
int b2;
virtual void foo() {}
};
struct Derived : public Base1, public Base2{
int d;
};
int main(){
Derived D;
Base2* p_B2 = &D;
std::cout << &D << "\n";
std::cout << p_B2 << "\n";
std::cout << sizeof( D) << "\n";
std::cout << sizeof( *p_B2) << "\n";
std::cout << &(D.b2) << "\n";
std::cout << &(p_B2->b2) << "\n";
return 0;
}
如果虚函数被注释掉,输出是这样的:
0x7fffffffdcb0
0x7fffffffde40
408
4
0x7fffffffde40
0x7fffffffde40
如果有虚函数,输出为:
0x7fffffffdca0
0x7fffffffdca0
416
16
0x7fffffffdca8
0x7fffffffdca8
大小的区别是v指针+padding,但是offset在哪里呢?为什么那些指向相同的地址?为什么 D 和 D.b2 之间应该至少有 100 个 int-s 而只有 8 个字节(我假设的 v 指针)差异?
(我的调试器 (gdb) 也将 p_B2 显示为 "Derived" 类型。)
编译器可以随意布局你的 类,大概你的编译器总是把虚拟 类 放在开头,然后是任何 non-virtual 类 .
您不能依赖 类 的任何特定顺序。
struct Base1{
int b1[100];
};
struct Base2{
int b2;
virtual void foo() {}
};
struct Derived : public Base1, public Base2{
int d;
};
int main(){
Derived D;
Base2* p_B2 = &D;
std::cout << &D << "\n";
std::cout << p_B2 << "\n";
std::cout << sizeof( D) << "\n";
std::cout << sizeof( *p_B2) << "\n";
std::cout << &(D.b2) << "\n";
std::cout << &(p_B2->b2) << "\n";
return 0;
}
如果虚函数被注释掉,输出是这样的:
0x7fffffffdcb0
0x7fffffffde40
408
4
0x7fffffffde40
0x7fffffffde40
如果有虚函数,输出为:
0x7fffffffdca0
0x7fffffffdca0
416
16
0x7fffffffdca8
0x7fffffffdca8
大小的区别是v指针+padding,但是offset在哪里呢?为什么那些指向相同的地址?为什么 D 和 D.b2 之间应该至少有 100 个 int-s 而只有 8 个字节(我假设的 v 指针)差异?
(我的调试器 (gdb) 也将 p_B2 显示为 "Derived" 类型。)
编译器可以随意布局你的 类,大概你的编译器总是把虚拟 类 放在开头,然后是任何 non-virtual 类 .
您不能依赖 类 的任何特定顺序。