Cpp 对象模型探索 / 静态联编和动态联编

一、源码

#include class Father
{
public:Father(){/*** 该处直接将该对象清零,意味着虚函数表指针亦被清零。*/memset(this, 0, sizeof(Father));}
public:virtual void Func1(){std::cout << "Fahter::Func1()" << std::endl;}virtual void Func2(){std::cout << "Fahter::Func2()" << std::endl;}virtual void Func3(){std::cout << "Fahter::Func3()" << std::endl;}
};int main()
{Father father;father.Func1();father.Func2();father.Func3();Father* pfather = new  Father();/*** 此处开始崩溃,因为虚函数表指针已经被清零。*/pfather->Func1();pfather->Func2();pfather->Func3();return 0;
}

结果

二、分析

问题,为什么含有虚函数的类,若是直接申请为实例对象,可以调用虚函数,但是通过指针 new 出的实例却崩溃呢?

原因,这里有个静态联编和动态联编的概念。

       静态联编的意思是在编译期间就能确定调用的函数的地址,即:call (地址),地址是确定的值。

       动态联编的意思是在运行期间才能确定调用的函数的地址。方法是通过对象的虚函数表指针找到虚函数表,再通过虚函数表找到虚函数,这也是多态的实现机理。而多态的实现,只针对指针或者引用。

       上述代码中,因为对象“father”不是指针或者引用,所以尽管存在虚函数,但是这些虚函数在不用在多态的情况下,其功能和普通函数是一样的,所以编译器直接将其按照静态编译来处理。

       针对上述代码中的"pfather",因为是 new 出的对象,所以编译器要考虑下面多态的可能性,所以调用虚函数是按照动态联编的调用顺序来调用的,即:虚函数表指针 --> 虚函数表 --> 虚函数 。但是,问题出在了“Father”类的构造函数中,因为该构造函数初始化对象的方法是直接将整个对象都初始化为0,这里面也包括虚函数表指针,所以,走多态的路来调用虚函数直接 Over 了。。所以上述通过 pfather 调用虚函数的方法就产生了崩溃。

 

(SAW:Game Over!)


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部