盐城市网站建设_网站建设公司_动画效果_seo优化
2026/1/6 10:38:55 网站建设 项目流程

先搞懂核心概念:多态(Polymorphism)

 
你可以把多态理解成:同一个行为,作用在不同对象上,表现出不同的效果
 
比如 “动物叫” 这个行为,猫叫是 “喵”,狗叫是 “汪”,用代码实现时,不用为每种动物写单独的调用逻辑,统一调用 “叫” 的方法,就能自动适配不同动物 —— 这就是多态的核心价值。
 
虚函数(virtual 函数) 是实现多态的 “开关”,虚析构函数 是多态场景下避免内存泄漏的 “补丁”。
 

 

一、虚函数:实现多态的核心

 

1. 什么是虚函数?

 
在基类的函数前加 virtual 关键字,这个函数就成了虚函数。它的作用是:告诉编译器,这个函数要 “晚绑定”(运行时才确定调用哪个版本),而不是 “早绑定”(编译时就确定)
 

2. 没有虚函数,就没有多态(反面例子)

 
cpp
 
运行
 
#include <iostream>
using namespace std;// 基类:动物
class Animal {
public:// 普通函数,没有virtualvoid makeSound() {cout << "未知动物叫" << endl;}
};// 派生类:猫
class Cat : public Animal {
public:void makeSound() { // 重写基类函数cout << "喵~" << endl;}
};// 派生类:狗
class Dog : public Animal {
public:void makeSound() { // 重写基类函数cout << "汪!" << endl;}
};int main() {Animal* a1 = new Cat(); // 基类指针指向派生类对象Animal* a2 = new Dog();a1->makeSound(); // 输出:未知动物叫(编译时绑定,只认基类)a2->makeSound(); // 输出:未知动物叫return 0;
}
 
 
问题:基类指针指向派生类对象时,调用的还是基类的函数,没法实现 “不同动物不同叫声”—— 这就是没有虚函数的问题。
 

3. 加虚函数,实现多态(正确例子)

 
只需要给基类的 makeSound()virtual
 
cpp
 
运行
class Animal {
public:// 虚函数:开启多态virtual void makeSound() {cout << "未知动物叫" << endl;}
};// 派生类代码不变
int main() {Animal* a1 = new Cat();Animal* a2 = new Dog();a1->makeSound(); // 输出:喵~(运行时绑定,认实际指向的对象)a2->makeSound(); // 输出:汪!delete a1;delete a2;return 0;
}
 
 
关键virtual 让函数调用从 “编译时确定” 变成 “运行时确定”,基类指针 / 引用会根据实际指向的派生类对象,调用对应的重写函数 —— 这就是动态多态
 

 

二、虚析构函数:多态场景下避免内存泄漏

 

1. 为什么需要虚析构函数?

 
当用基类指针指向派生类对象,并且派生类有自己的成员变量(需要析构)时,如果基类析构函数不是虚函数,删除基类指针只会调用基类的析构函数,派生类的析构函数不会被调用 —— 导致内存泄漏。
 

2. 反面例子(非虚析构函数)

 
cpp
 
运行
#include <iostream>
using namespace std;class Animal {
public:virtual void makeSound() { cout << "未知动物叫" << endl; }// 普通析构函数,没有virtual~Animal() { cout << "Animal析构" << endl; }
};class Cat : public Animal {
private:int* data = new int(10); // 动态分配内存
public:void makeSound() { cout << "喵~" << endl; }// 派生类析构函数:释放data~Cat() {delete data;cout << "Cat析构(释放data)" << endl;}
};int main() {Animal* a = new Cat();a->makeSound(); // 正常输出:喵~delete a; // 删除基类指针return 0;
}
 
 
输出结果
 
plaintext
 
喵~
Animal析构
 
 
问题Cat 的析构函数没被调用,data 指向的内存没释放 —— 内存泄漏!
 

3. 加虚析构函数(正确做法)

 
只需要给基类的析构函数加 virtual
 
cpp
 
运行
class Animal {
public:virtual void makeSound() { cout << "未知动物叫" << endl; }// 虚析构函数virtual ~Animal() { cout << "Animal析构" << endl; }
};
 
 
输出结果
 
plaintext
喵~
Cat析构(释放data)
Animal析构
 
 
关键:虚析构函数会让 delete 基类指针 时,先调用派生类的析构函数,再调用基类的 —— 保证所有资源都被释放。
 
🌟 小技巧:如果一个类是基类,并且可能被继承、用多态方式使用,建议直接把析构函数设为虚函数,哪怕暂时没有派生类。
 
 

 

三、核心规则总结

 
  1. 虚函数:基类函数加 virtual,派生类重写该函数,通过基类指针 / 引用调用时,会执行实际对象的函数版本 —— 实现动态多态。
  2. 虚析构函数:基类析构函数加 virtual,保证用基类指针删除派生类对象时,派生类析构函数会被调用,避免内存泄漏。
  3. 多态的前提:① 继承关系;② 基类有虚函数;③ 派生类重写虚函数;④ 通过基类指针 / 引用调用函数。
 

 

总结

 
  • 虚函数是多态的 “开关”:没有它,多态就无法实现,基类指针只能调用基类自己的函数;
  • 虚析构函数是多态的 “兜底保障”:没有它,派生类的资源会泄漏,是多态场景下的必做优化;
  • 多态的本质:通过虚函数表(vtable)实现运行时函数绑定,让代码更灵活、易扩展(比如新增 “鸟” 类,不用改原有调用逻辑)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询