多态
多态(polymorphism)是面向对象编程的核心特性之一。通俗理解,就是'同一接口,不同表现'。它让同一个函数调用在不同对象上产生不同的行为,从而大幅提升代码的复用性与扩展性。
一、多态的概念
多态分为编译时多态(静态多态)和运行时多态(动态多态)。本文重点讨论运行时多态。
编译时多态主要依赖函数重载和模板,通过参数类型匹配在编译期确定调用哪个函数。而运行时多态则是通过基类指针或引用调用虚函数,实际执行哪个版本取决于对象的具体类型。比如买票场景:普通人全价,学生优惠,军人优先;或者动物叫:猫叫喵,狗叫汪。核心在于行为相同,但具体实现因对象而异。
二、多态的定义及实现条件
多态通常发生在继承体系下。当基类的指针或引用指向派生类对象,并调用虚函数时,就会触发多态。
要实现多态效果,必须满足两个关键条件:
- 必须是基类的指针或引用:只有这样才能同时指向基类和派生类对象。
- 被调用的函数必须是虚函数且完成重写:派生类需对基类虚函数进行覆盖,否则无法体现差异。
1. 虚函数与重写
在成员函数前加 virtual 关键字即可声明为虚函数。非成员函数不能加此修饰符。
class Person {
public:
virtual void BuyTicket() {
cout << "买票全价" << endl;
}
};
class Student : public Person {
public:
virtual void BuyTicket() {
cout << "买票半价" << endl;
}
};
注意:派生类重写虚函数时,即使不写 virtual 关键字,只要签名一致,依然构成重写(因为继承了虚属性),但为了代码规范,建议显式写出。
2. 重写的细节问题
- 协变:如果基类虚函数返回基类指针/引用,派生类重写时可返回派生类指针/引用。这称为协变,主要用于优化内存模型。
- 析构函数的重写:这是面试高频点。如果基类析构函数不是虚函数,通过基类指针删除派生类对象时,只会调用基类析构函数,导致派生类资源泄漏。因此,基类析构函数建议设计为虚函数。
class A {
public:
virtual ~A() { cout << "~A()" << endl; }
};
class B : A {
:
~() { cout << << endl; _p; }
:
* _p = [];
};
{
A* p2 = B;
p2;
;
}


