Cpp 对象模型探索 / 继承关系下的虚函数手动调用

一、多态机理

#include class 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;}private:size_t count_;
};class Son : public Father
{
public:virtual void Func2(){std::cout << "Son::Func2()" << std::endl;}
};using FUNC = void (*)();int main()
{Father *pfather = new Father;Son *pson = new Son;// 得到指向虚函数表指针的地址。long *pvptr_father = (long *)pfather;long *pvptr_son = (long *)pson;// 得到指向虚函数表的指针。    long *vptr_father = (long *)(*pvptr_father); long *vptr_son = (long *)(*pvptr_son); FUNC func1_father, func2_father, func3_father;func1_father = (FUNC) * (vptr_father + 0); // 得到虚函数 Father::Func1() 的地址。func2_father = (FUNC) * (vptr_father + 1); // 得到虚函数 Father::Func2() 的地址。func3_father = (FUNC) * (vptr_father + 2); // 得到虚函数 Father::Func2() 的地址。func1_father();func2_father();func3_father();std::cout << std::endl;FUNC func1_son, func2_son, func3_son;func1_son = (FUNC) * (vptr_son + 0); // 得到虚函数 Father::Func1() 的地址。func2_son = (FUNC) * (vptr_son + 1); // 得到虚函数 Son::Func2() 的地址。func3_son = (FUNC) * (vptr_son + 2); // 得到虚函数 Father::Func2() 的地址。func1_son();func2_son();func3_son();return 0;
}

结果:

Son sn;
Father fa = sn;
fa.Func1();
fa.Func2();
fa.Func3();

结果:

Fahter::Func1()
Fahter::Func2()
Fahter::Func3()

       对于多态,使用指针或者引用,用父类调用子类的函数达到工厂模式的目的。倘若用子类直接赋值给父类,会有什么结果呢。上述代码就展示了最后的结果,并没有调用子类的函数,而是直接调用了父类的函数。

       原因是直接用子类给父类对象赋值,子类中的属于父类部分内容会被编译器自动切割出来并拷贝给了父类

       实际上上述操作一共干了两件事情,

       1、生成 Father 对象。

       2、用 sn 来初始化 Father 对象。显然,编译器并没有将 sn 的虚函数表指针覆盖掉 fa 的虚函数表指针。

四、总结

1、类只有包含了虚函数才存在虚函数表(只有一个),同属于一个类的对象共享虚函数表,但是有各自的vptr(虚函数表指针)。

2、父类含有虚函数,子类就会有一个虚函数表,但是子类的虚函数表只是和父类的虚函数表中的内容相同,所在的内存位置不同。

3、多态是子类赋值给父类的指针或者引用。若直接对象赋值,是对象切割的范畴。

 

(SAW:Game Over!)


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

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部