虚函数 vs 纯虚函数 vs 静态函数(C++)
🧩 一图看懂:虚函数 vs 纯虚函数
特性 | 虚函数(Virtual) | 纯虚函数(Pure Virtual) |
---|---|---|
语法 | virtual void foo(); | virtual void foo() = 0; |
是否必须实现 | ✅ 必须在类中实现 | ❌ 不在基类实现,派生类必须实现 |
是否可被重写 | ✅ 可重写(override) | ✅ 必须被重写(override) |
用途 | 支持运行时多态,可选重写 | 强制派生类必须重写,实现接口规范 |
是否构成抽象类 | ❌ 不一定 | ✅ 是抽象类,不能实例化 |
✅ 虚函数(virtual
)
-
语法:
virtual void speak();
-
作用:支持 运行时多态
-
特性:
-
有默认实现
-
可以被子类覆盖
-
必须是非静态成员函数
-
-
使用场景:需要在子类中覆盖行为(但不是强制)
✅ 纯虚函数(= 0
)
-
语法:
virtual void speak() = 0;
-
作用:创建接口函数,强制子类必须实现
-
特性:
-
没有默认实现
-
子类 必须重写,否则也是抽象类
-
所在类称为 抽象类,不能被实例化
-
-
用途:面向接口编程、设计规范
class Animal {
public:
virtual void speak() = 0; // 纯虚函数
};
✅ 静态成员函数(static
)
-
属于类本身,而不是对象
-
❌ 不能是虚函数,因为没有 this 指针
-
无法访问非静态成员(因为不依赖对象)
class A {
public:
static void sayHello(); // 和对象无关
};
🧠 三、抽象类(包含纯虚函数的类)
-
语法:类中至少一个函数是
virtual void foo() = 0;
-
特点:
-
不能被实例化
-
派生类必须实现纯虚函数,才可以实例化
-
通常作为接口使用,规范子类的行为
-
📌 四、虚函数工作原理:虚函数表(vtable)
-
编译器为类创建一张虚函数表
-
对象内部有个隐藏指针指向这个表(vptr)
-
当你调用虚函数时,实际会通过 vtable 找到正确的函数地址 ➜ 实现多态
🔑 小结:口诀记忆版
项目 | 口诀 |
---|---|
const 指针 | 左定值,右定向,const 修饰不变量 |
虚函数 | 支持多态,可选覆盖 |
纯虚函数 | 没有实现,强制子类实现,是接口 |
抽象类 | 有纯虚函数,不可实例化,只能继承 |
静态函数 | 类级函数,不能访问对象成员,不能是虚函数 |
多态原则 | 通过指针/引用访问虚函数,才会发生运行时多态 |
析构函数 | 如果类有虚函数,析构函数也应为虚函数,防止内存泄漏 |
详情请见:C++ 虚函数和纯虚函数的区别 | 菜鸟教程