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

【c++知识归纳】继承与多态(二)

2016-08-26 04:50 513 查看
在继承与多态(一)中简单介绍了继承与多态的基础知识,本文将从内存中深入理解c++的继承与多态。
本文我选用了较低版本的IDE:【windows 10】系统的vs2008,因为高版本的处理比较复杂,为了看的更清楚,我们选择这个较低版本的编译器。

1.虚函数表(虚表)
class Base
{
public:
Base()
:_b(1)
{}
virtual void fun()
{
cout << "Base::fun()" << endl;
}
protected:
int _b;
};<pre class="cpp" name="code">int main()
{
Base b;
system("pause");
return 0;
}


调试上面的代码,打开监视和内存:


 
虚函数表:通过一块连续的内存来存储虚函数的地址。虚表指针指向这一块连续的空间。

2.单继承的对象模型
通过下面的代码来探索
class Base
{
public:
Base()
:_b(1)
{}
virtual void fun1()
{
cout << "Base::fun1()" << endl;
}
virtual void fun2()
{
cout << "Base::fun2()" << endl;
}
protected:
int _b;
};

class Derive:public Base
{
public:
Derive()
:_d(2)
{}
virtual void fun1()
{
cout << "Derive::fun1()" << endl;
}
virtual void fun3()
{
cout << "Derive::fun3()" << endl;
}
protected:
int _d;
};
typedef void(*pfun)();
void PrintVfptr(pfun *ppfun)//调用虚表中的函数
{
for (int i = 0; ppfun[i] != NULL; i++)
{
ppfun[i]();
}
}
void test()
{
Derive d;
PrintVfptr((pfun*)(*(int *)&d));
}
int main()
{
test();
system("pause");
return 0;
}

同样,调试上面这段代码,打开内存和监视,来探索单继承子类对象在内存中的存储。



通过上面图片的分析,可以看到,当子类重写了父类的虚函数后,子类的函数地址直接将父类原来的函数地址覆盖,即虚表中的函数地址已经改为子类的函数地址了。所以当我们用父类的指针指向子类的对象时,调用的是子类重写的虚函数,这样就实现了多态。

3.多重继承的对象模型
class Base1
{
public:
Base1()
:_b1(1)
{}
virtual void fun()
{
cout << "Base1::fun()" << endl;
}
virtual void fun1()
{
cout << "Base1::fun1()" << endl;
}
protected:
int _b1;
};

class Base2
{
public:
Base2()
:_b2(2)
{}
virtual void fun()
{
cout << "Base2::fun()" << endl;
}
virtual void fun2()
{
cout << "Base2::fun2()" << endl;
}
protected:
int _b2;
};

class Derive :public Base1, public Base2
{
public:
Derive()
:_d(3)
{}
virtual void fun()
{
cout << "Derive::fun()" << endl;
}
virtual void fun2()
{
cout << "Derive::fun1()" << endl;
}
virtual void fun3()
{
cout << "Derive::fun3()" << endl;
}
protected:
int _d;
};

typedef void(*pfun)();
void PrintVfptr(pfun* ppfun)
{
for (int i = 0; ppfun[i] != NULL; i++)
{
ppfun[i]();
}
}
void test()
{
Derive d;
printf("第1个虚表\n");
PrintVfptr((pfun*)(*(int*)&d));
printf("第2个虚表\n");
PrintVfptr((pfun*)(*((int*)&d+2)));
}
int main()
{
test();
system("pause");
return 0;
}




通过上图的分析,可以总结如下规律:
(1)有n个基类,则派生类就有n个虚表指针,也就有n个虚表。
(2)多重继承最左端的基类,它的虚表为主要表格,其中包含着Derive类的多有虚函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息