深入理解多态:从虚函数表到底层实现
一、多态的概念
1.1 编译时多态
编译时多态主要体现为函数重载和模板。它们通过传递不同类型的参数来实现,之所以称为'编译时',是因为参数的匹配在编译阶段就已经完成。这种机制也被称为静态绑定。
1.2 运行时多态
运行时多态则是通过对象本身来区分行为,而编译时多态是通过类型区分的。就像同样是'叫'这个行为,传入猫的对象就是'喵喵',传入狗的对象就是'汪汪'。
二、多态的定义和使用
2.1 多态的判定标准
要实现多态,通常需要满足三个条件:
- 使用基类的指针或引用进行调用。
- 被调用的函数必须是虚函数。
- 派生类中必须存在对该函数的重写(Override)。
为什么一定要用基类的指针或引用? 多态的核心在于'运行时确定'。如果使用基类对象直接调用,编译器在编译期就能明确知道对象类型,无法触发动态查找。只有当使用指针或引用时,运行前才不知道具体指向的类型,此时需要查询虚函数表,从而实现'运行时确认'。
2.1.1 虚函数
在函数声明前加上 virtual 关键字,该函数即成为虚函数。
virtual void func();
2.1.2 函数重写
函数重写需满足以下条件:
- 两个函数的函数名、参数列表、返回值类型完全一致。
- 两个函数均为虚函数。
补充一点:派生类中的函数即使没有显式声明 virtual 也是可以的,因为基类中的 virtual 关键字会被继承。此时重写后的函数相当于将基类的声明与派生类的实现结合在了一起。
2.2 相关题目分析
以下程序输出结果是什么?
#include <iostream>
using namespace std;
class A {
public:
virtual void func(int val = 1) {
cout << "A->" << val << endl;
}
virtual void test() {
func();
}
};
class : A {
:
{
cout << << val << endl;
}
};
{
B* p = B;
p->();
p;
;
}



