涂有薄技涂宗勋 2010-12-12
C++中基类的构造函数调用虚函数的问题以及ATL_NO_VTBL宏
class Base{
public:
base(){init();}
virtual void init(){};
} class Derived:public Base{
pubic:
virtual void init(){}
}
在这个例子中,在Derived对象构造的过程中,Base的构造函数中调用的init并不是Derived:init,而是Base::int!!!
这样做有充足的理由:在派生类被正确地构造出来之前,调用派生类的虚成员函数并没有意义,但是,一直要到基类被构造之后,派生类才会被正确地构造。为了保证在构造期间只能调用已经被正确构造的类的函数,c++编译器建立了两个vtbl,一个为Base,另一个为Derived,随后C++运行库会在构造序列期间调整vptr使它指向适当的vtbl(注意:由上可以看出,编译器和运行库的共同作用实现了这个做法)。由于上述情况很少遇到,所以vc中引入了__declspec(novtbl)来禁止在构造期间对vptr的调整。当基类是一个抽象基类时,经常导致编译器产生了vtbl,但是并没有使用它,因此连接器把他们从最终的映像中删除。ATL_NO_VTBL宏就是使用了这项优化。另外:因为在构造时关闭了对vtbl的调整,所以在析构时也关闭了对vtbl的调整,因此,在析构函数中也要避免使用虚成员函数。 【6688电子商务网站 www.6688.cc 】
在Linux中做C++程序中碰到过一次:
在基类构造函数中启动一个线程,发现在这个线程函数中调用的虚函数都是调用的基类的。可能也是这个原因
PS:遇到有时需要在构造函数中调用虚函数的情况,可以将调用函数语句放到Derived的构造函数中,而不是Base的,以避免此问题。
是一道经常出现在前端面试时的问题。如果只是简单的了解new关键字是实例化构造函数获取对象,是万万不能够的。更深入的层级发生了什么呢?同时面试官想从这道题里面考察什么呢?下面胡哥为各位小伙伴一一来解密。