您的位置:首页 > 编程语言 > C语言/C++

C++ 多态性 -- 虚函数表(2)

2018-03-16 14:39 225 查看
2018-03-15  创建人:Ruo_Xiao
开发环境:VS2010
邮箱:xclsoftware@163.com
参考链接:http://blog.csdn.net/haoel/article/details/1948051/
上文链接:http://blog.csdn.net/itworld123/article/details/79578014


一、多重继承 – 无覆盖

#include "stdafx.h"
#include <iostream>
using namespace std;

class Father_1
{
public:
virtual void F_Say_1_1()
{
cout << "Father Say 11" << endl;
}

virtual void F_Say_1_2()
{
cout << "Father Say 12" << endl;
}

virtual void F_Say_1_3()
{
cout << "Father Say 13" << endl;
}

};

class Father_2
{
public:
virtual void F_Say_2_1()
{
cout << "Father Say 21" << endl;
}

virtual void F_Say_2_2()
{
cout << "Father Say 22" << endl;
}
};

class Father_3
{
public:
virtual void F_Say_3_1()
{
cout << "Father Say 31" << endl;
}
};

class Son:public Father_1,public Father_2,public Father_3
{
public:
virtual void S_Say_1()
{
cout << "Son Say 1" << endl;
}

virtual void S_Say_2()
{
cout << "Son Say 2" << endl;
}

virtual void S_Say_3()
{
cout << <
4000
span class="hljs-string">"Son Say 3" << endl;
}
};

typedef void(*Fun)(void);
int main()
{
Son S;
Fun pFun_1 = NULL;
Fun pFun_2 = NULL;
Fun pFun_3 = NULL;
Fun pFun_4 = NULL;
Fun pFun_5 = NULL;
Fun pFun_6 = NULL;
Fun pFun_7 = NULL;
Fun pFun_8 = NULL;
Fun pFun_9 = NULL;

cout << "虚函数表地址:" << (int *)(&S) << endl;
cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&S) << endl;

pFun_1 = (Fun)*((int *) *(int *)(&S)+0);
pFun_2 = (Fun)*((int *) *(int *)(&S)+1);
pFun_3 = (Fun)*((int *) *(int *)(&S)+2);
pFun_4 = (Fun)*((int *) *(int *)(&S)+3);
pFun_5 = (Fun)*((int *) *(int *)(&S)+4);
pFun_6 = (Fun)*((int *) *(int *)(&S)+5);

pFun_7 = (Fun)*((int *) *(int *)(&S)+7);
pFun_8 = (Fun)*((int *) *(int *)(&S)+8);

pFun_9 = (Fun)*((int *) *(int *)(&S)+10);

cout<<"Father_1和Son 虚表"<<endl;
pFun_1();
pFun_2();
pFun_3();
pFun_4();
pFun_5();
pFun_6();
cout<<endl;
cout<<"Father_2 虚表"<<endl;
pFun_7();
pFun_8();
cout<<endl;
cout<<"Father_3 虚表"<<endl;
pFun_9();

cin.get();
}


结果:



由上述结果可知:

1、子类的虚表中会保留所有的父类的虚表,其排布顺序和继承的顺序相同。

2、子类的虚函数会跟在第一个父类的虚表的后面。

3、上述栗子中虚表的排布如下图所示:



(1)图片中,蓝色代表父类Father_1,绿色代表父类Father_2,紫色代表父类Father_3。

(2)各个父类的虚表是连续的,并且以各自的结束符“NULL”为标志。

4、有上述可知,代码中没有“+6”和“+9”,因为二者对应的是NULL。

二、多重继承 – 有覆盖

#include "stdafx.h"
#include <iostream>
using namespace std;

class Father_1
{
public:
virtual void F_Say_1()
{
cout << "Father Say 1" << endl;
}

virtual void F_Say_1_2()
{
cout << "Father Say 12" << endl;
}

virtual void F_Say_1_3()
{
cout << "Father Say 13" << endl;
}

};

class Father_2
{
public:
virtual void F_Say_1()
{
cout << "Father Say 1" << endl;
}

virtual void F_Say_2_2()
{
cout << "Father Say 22" << endl;
}
};

class Father_3
{
public:
virtual void F_Say_1()
{
cout << "Father Say 1" << endl;
}
};

class Son:public Father_1,public Father_2,public Father_3
{
public:
virtual void F_Say_1()
{
cout << "Son Say 1" << endl;
}

virtual void F_Say_1_2()
{
cout << "Son Say 2" << endl;
}

virtual void F_Say_2_2()
{
cout << "Son Say 3" << endl;
}
};

typedef void(*Fun)(void);
int main()
{
Son S;
Fun pFun_1 = NULL;
Fun pFun_2 = NULL;
Fun pFun_3 = NULL;
Fun pFun_4 = NULL;
Fun pFun_5 = NULL;
Fun pFun_6 = NULL;

cout << "虚函数表地址:" << (int *)(&S) << endl;
cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&S) << endl;

pFun_1 = (Fun)*((int *) *(int *)(&S)+0);
pFun_2 = (Fun)*((int *) *(int *)(&S)+1);
pFun_3 = (Fun)*((int *) *(int *)(&S)+2);
pFun_4 = (Fun)*((int *) *(int *)(&S)+4);
pFun_5 = (Fun)*((int *) *(int *)(&S)+5);
pFun_6 = (Fun)*((int *) *(int *)(&S)+7);

cout<<"Father_1和Son 虚表"<<endl;
pFun_1();
pFun_2();
pFun_3();
cout<<endl;
cout<<"Father_2 虚表"<<endl;
pFun_4();
pFun_5();
cout<<endl;
cout<<"Father_3 虚表"<<endl;
pFun_6();

cin.get();
}


结果:



有上述结果可知:若多个父类中有相同名字的虚函数,而且子类重写的该虚函数,则在虚表中,所有的父类的该虚函数均被覆盖。

(SAW:Game Over!)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: