基于PJ85718DM与PIC18F87J11的本地及远程温度监测方案
2026/10/10 14:06:37
C++ 多态详解(从基础到工程实践)
多态(Polymorphism)是面向对象编程的三大特性之一,在 C++ 中主要通过虚函数(virtual function)实现,是 C++ 中最强大也最容易出错的特性之一。
下面从原理 → 用法 → 细节 → 常见陷阱 → 工程实践,一次性把 C++ 多态讲透。
C++ 中的多态指的是:
“同一个接口,不同实现”
通过基类指针或引用调用虚函数时,实际执行的是派生类的版本,而不是基类的版本。
一句话总结:
“父类指针(或引用)指向子类对象时,通过虚函数调用子类的实现”
#include<iostream>usingnamespacestd;classAnimal{public:// 声明为虚函数virtualvoidspeak()const{cout<<"Animal is speaking...\n";}virtual~Animal()=default;// 虚析构函数(非常重要!)};classDog:publicAnimal{public:voidspeak()constoverride{// override 是 C++11 推荐写法cout<<"Woof! Woof!\n";}};classCat:publicAnimal{public:voidspeak()constoverride{cout<<"Meow~\n";}};intmain(){Animal*animal1=newDog();Animal*animal2=newCat();animal1->speak();// 输出:Woof! Woof!animal2->speak();// 输出:Meow~deleteanimal1;deleteanimal2;return0;}关键点:
virtual只能在基类中首次声明virtual,但强烈建议写override(编译器会检查是否真的重写)C++ 通过虚函数表(vtable)实现多态。
内存布局示意(Dog 对象):
Dog 对象内存: [ vptr ] → 指向 Dog 的 vtable [ 其他成员 ] Dog 的 vtable: [ &Dog::speak ] [ &Animal::~Animal ] // 虚析构函数 ...| 特性 | 普通成员函数 | 虚函数 (virtual) |
|---|---|---|
| 是否多态 | 否 | 是 |
| 调用方式 | 静态绑定(编译期确定) | 动态绑定(运行期通过 vptr) |
| 开销 | 几乎无 | 一次虚表指针查找 + 间接调用 |
| 是否可以被 override | 否 | 是 |
| 析构函数 | 一般不虚 | 必须虚(否则内存泄漏风险) |
永远记住:只要一个类可能被当作基类使用,就要把析构函数写成虚函数!
classBase{public:// 非虚析构 → 大坑!// ~Base() { cout << "Base dtor\n"; }virtual~Base(){cout<<"Base dtor\n";}};classDerived:publicBase{public:~Derived(){cout<<"Derived dtor\n";}};intmain(){Base*p=newDerived();deletep;// 如果 ~Base() 非虚,只调用 Base 析构 → 内存泄漏// 如果是虚析构 → 先 Derived → 再 Base}结论:
voidmakeSound(Animal animal){// 值传递 → 切片animal.speak();// 永远调用 Animal::speak()}正确写法:
voidmakeSound(constAnimal&animal){// 引用或指针animal.speak();}classBase{public:virtualvoidfunc()const=0;// 纯虚函数};classDerived:publicBase{public:voidfunc()constoverridefinal{// 强制重写 + 禁止再被重写cout<<"Derived func\n";}};classBase{public:Base(){who();}// 危险!virtualvoidwho(){cout<<"Base\n";}};classDerived:publicBase{public:voidwho()override{cout<<"Derived\n";}};→ 构造 Base 时,Derived 还没构造完成,who() 调用的是 Base 版本
virtualvoidprint(intx=10);→ 调用时用的是声明处的默认参数,不是实际类型的
const Animal&)dynamic_cast(有开销)想深入哪一部分?
比如:
告诉我具体想看哪一块,我可以继续展开代码和图解。