多态原理
关于多态的相关概念我已经在上一篇博客中总结了,这里主要是更深入的去探索多态,上一篇的博客链接如下:
我们已经知道多态是什么了,那么多态是如何实现的?其实就是虚函数表,我们先来看一看虚函数表的作用
虚函数表
写一段代码:
class Base{
public:
Base()
:a(1)
{}
virtual void func1() {}
virtual void func2() {}
private:
int a;
};
void Test() {
Base b;
}
实例化一个对象b之后,我们查看一下内存中对象b都有什么,如图:
我们发现,有一个整型变量a和一个地址,这个类的对象模型是这样的:
我们知道,这个类中是有两个虚函数的,那么这个地址是不是跟虚函数有关呢?我们查看一下这个地址
我们发现,这个地址里面存储的是两个地址,那么这两个地址是不是类Base里两个虚函数的地址呢?我们对Test()函数进行修改,显式的调用func1和func2函数,代码如下:
void Test() {
Base b;
b.func1();
b.func2();
}
然后查看反汇编代码:
我们发现,这个两个地址就是对象b里面func1和func2函数的地址
所以,在这个类的对象模型里面,一开始存放的地址,指向一个表,这个表就是虚函数表,里面存储的是虚函数,并且以NULL指针结尾,对象b的对象模型如图所示:
其实编译器的监视窗口里面是可以看到虚函数表的,如:
我们已经知道了虚函数表是什么,那多态又是如何用虚函数表实现呢?
单继承下的多态对象模型
我们写一段代码:
class Base{
public:
Base()
:b(1)
{}
virtual void func1() {}
virtual void func2() {}
protected:
int b;
};
class Derive : public Base {
public:
Derive()
:Base()
, d(2)
{}
virtual void func1() {}
virtual void func2() {}
virtual void func3() {}
protected:
int d;
};
void Test() {
Base b;
Derive d;
d.func1();
d.func2();
d.func3();
}
定义了一个基类Base和一个派生类Derive,然后实例化出一个派生类的对象d,接下来我们借用vs2013调试时的监视窗口和内存窗口以及反汇编代码来查看
我们以前在继承的时候探讨