这里面说了一种情况:
class Base {
virtual function() = 0;
};
class B : public Base{
virtual function() {
....
}
};
class A {
A(B* b) : _b(b) {}
~A {
_b->function();
}
B* _b;
};
B b;
A a(&b);
主要的原因是因为全局变量的释放顺序不确定,全局变量A依赖全局变量B。
如果编译器决定让B先释放,A后释放。那么,当A析构时,_b是一个dangling pointer。此时如果b对象的内存系统没有释放的话,那么b的vptr表指向的是Base的vptr,而不是B的。此时,_b->function()就指向了pure virtual function了。
实际上,在每一个类(当然是多态类了)的构造函数和析构函数中,编译器都会重新修正每一个vptr的值,使它们指向当前类的vtable。至于在各自的vtable中的虚函数指针是指向基类的虚函数还是指向该类改写的虚函数,这就取决于用户在该类中是否改写基类的虚函数了。
@小名阿铁
因为Base析构时可能要用到自己的vptr表(它析构时要调用自己或者它父类的虚函数),但如果这个对象本身是它的派生类对象(B)的话,那么如果不修改vptr表的话,可能调用的就是它的派生类(B)的虚函数了。但这时派生类的析构函数已经被调用过了,基类不能调用派生类的任何函数。所以,必须在调用Base析构函数之前,系统必须先将对象的vptr表设置为Base的vptr表。
另外
http://blog.youkuaiyun.com/vigour_lu/archive/2009/08/07/4422133.aspx
该网址有更多详细的信息。
class Base {
virtual function() = 0;
};
class B : public Base{
virtual function() {
....
}
};
class A {
A(B* b) : _b(b) {}
~A {
_b->function();
}
B* _b;
};
B b;
A a(&b);
主要的原因是因为全局变量的释放顺序不确定,全局变量A依赖全局变量B。
如果编译器决定让B先释放,A后释放。那么,当A析构时,_b是一个dangling pointer。此时如果b对象的内存系统没有释放的话,那么b的vptr表指向的是Base的vptr,而不是B的。此时,_b->function()就指向了pure virtual function了。
实际上,在每一个类(当然是多态类了)的构造函数和析构函数中,编译器都会重新修正每一个vptr的值,使它们指向当前类的vtable。至于在各自的vtable中的虚函数指针是指向基类的虚函数还是指向该类改写的虚函数,这就取决于用户在该类中是否改写基类的虚函数了。
@小名阿铁
因为Base析构时可能要用到自己的vptr表(它析构时要调用自己或者它父类的虚函数),但如果这个对象本身是它的派生类对象(B)的话,那么如果不修改vptr表的话,可能调用的就是它的派生类(B)的虚函数了。但这时派生类的析构函数已经被调用过了,基类不能调用派生类的任何函数。所以,必须在调用Base析构函数之前,系统必须先将对象的vptr表设置为Base的vptr表。
另外
http://blog.youkuaiyun.com/vigour_lu/archive/2009/08/07/4422133.aspx
该网址有更多详细的信息。