1 多态的实现需要使用引用或者指针
1.1 指针和引用是实现多态的必要条件
EG:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void func()
{
cout << "Base" << endl;
}
};
class Son:public Base
{
public:
virtual void func()
{
cout << "Son" << endl;
}
};
int main()
{
Base *son1 = new Son();
son1->func(); //可以实现多态,打印 "Son"
Base son2 = Son();
son2.func(); //不能实现多态,打印 "Base"
return 0;
}
在《深度探索C++对象模型》找到了答案:一个pointer或一个reference之所以支持多态,是因为它们并不引发内存任何“与类型有关的内存委托操作; 会受到改变的。只有它们所指向内存的大小和解释方式
所以直接赋值的方式会导致对象切割,而使用指针或者引用只是改变了对内存的解释方式,并没有改变对象类型
1.2 当我们没有使用指针或者引用,调用虚函数不会通过虚函数表指针查找虚函数
当我们直接赋值,不使用指针或者引用,调用虚函数采用的是静态联编,而如果使用指针或者引用,调用虚函数采用的是动态联编
EG:
#include <iostream>
using namespace std;
class A
{
public:
int a;
virtual void funcA()
{
cout << "funcA虚函数" << endl;
}
};
int main()
{
A a;
memset(&a, 0, sizeof(A));
cout << a.a << endl; //打印 0
a.funcA(); //尽管上面已经使用 memset函数将虚函数表指针赋值为0,但是这行代码依然可以执行
//因为查看反汇编代码会发现这行代码是静态联编
A *a1 = new A();
a1->funcA(); //查看反汇编会发现这行代码是动态联编,如果将这个实例的虚函数表指针破坏,那么这行代码执行就会报异常
return 0;
}
提示:在VS中调试,打开反汇编就可以查看汇编代码
2 虚函数表指针位置
2.1 虚函数表指针位置
虚函数表的地址总是存在于对象实