作者在 2011-04-06 22:28:05 发布以下内容
静态联编和动态联编的本质区别:指向每一个虚函数的指针存在于一个叫虚函数表(vtbl)中,虚函数表的指针位于类对象内存块的第一个slot,而成员函数呢,只是指针存在于内存块中,并不存在什么虚函数表。那当在类的构造函数和析构函数中调用虚函数,是静态联编还是动态联编?分析下面代码:
class Base
{
public:
Base(){}
~Base()
{
print();
}
virtual void print()
{
cout<<"Base - print"<<endl;
}
};
class Derive : public Base
{
public:
Derive(){}
~Derive(){}
virtual void print()
{
cout<<"Derive - print"<<endl;
}
};
void OutPrint(Base *pObj)
{
pObj->print();
}
void main()
{
Derive Obj;
OutPrint(&Obj);
}
结果:Derive - print
Base - print
第一行:动态联编,这很好理解,但第二行到底是静态还是动态,即到底是编译期间确定调用哪个虚函数还是运行期间?
{
public:
Base(){}
~Base()
{
print();
}
virtual void print()
{
cout<<"Base - print"<<endl;
}
};
class Derive : public Base
{
public:
Derive(){}
~Derive(){}
virtual void print()
{
cout<<"Derive - print"<<endl;
}
};
void OutPrint(Base *pObj)
{
pObj->print();
}
void main()
{
Derive Obj;
OutPrint(&Obj);
}
结果:Derive - print
Base - print
第一行:动态联编,这很好理解,但第二行到底是静态还是动态,即到底是编译期间确定调用哪个虚函数还是运行期间?
如果将代码~Derive(){}改成~Derive(){ Base *p=new Derive; p->print();delete p; }结果是: Derive - print
Derive - print
Base - print
Base - print
如果是静态联编,那么代码更改后第二行应该是Base-print,但实际上是在运行时确定调用派生类虚函数,其实书上所说的构造函数和析构函数调用虚函数是静态联编,不怎么严谨,我想应该是在调用基类构造函数和析构函数之中,调用虚函数时,被逼无奈的动态联编,事实上是在运行是确定的,但没办法,第一:对象初始化时,要先初始化基类成员,只能调用基类的虚函数,第二:当对象销毁时,要先撤销派生类成员的内存空间,所以等到执行基类析构函数,调用虚函数时,只剩下基类的虚函数。
Derive - print
Base - print
Base - print
如果是静态联编,那么代码更改后第二行应该是Base-print,但实际上是在运行时确定调用派生类虚函数,其实书上所说的构造函数和析构函数调用虚函数是静态联编,不怎么严谨,我想应该是在调用基类构造函数和析构函数之中,调用虚函数时,被逼无奈的动态联编,事实上是在运行是确定的,但没办法,第一:对象初始化时,要先初始化基类成员,只能调用基类的虚函数,第二:当对象销毁时,要先撤销派生类成员的内存空间,所以等到执行基类析构函数,调用虚函数时,只剩下基类的虚函数。