
多态概述
多态(polymorphism)是面向对象编程的灵魂之一。简单来说,就是'同一接口,多种形态'。它让同一个函数在不同对象上表现出不同的行为,从而大大提升了代码的复用性、扩展性与灵活性。
多态分为编译时多态(静态多态)和运行时多态(动态多态)。编译时多态主要通过函数重载和模板实现,实参匹配在编译期完成;而本文重点讨论运行时多态,即通过基类指针或引用调用虚函数,在运行期根据实际对象类型决定执行哪个函数。
多态的实现条件
要实现运行时多态,必须同时满足以下两个条件:
- 继承关系:必须是派生类对象通过基类的指针或引用进行访问。
- 虚函数重写:被调用的函数必须是虚函数,且派生类中完成了对基类虚函数的重写(Override)。
如果只满足其中一个条件,比如没有使用指针或引用,或者函数没有声明为 virtual,那么发生的是静态绑定,无法体现多态效果。
虚函数与重写
在 C++ 中,成员函数前加 virtual 关键字修饰,该函数即为虚函数。非成员函数不能加 virtual。
class Person {
public:
virtual void BuyTicket() {
cout << "买票全价" << endl;
}
};
class Student : public Person {
public:
virtual void BuyTicket() {
cout << "买票半价" << endl;
}
};
当通过基类指针调用 BuyTicket 时,程序会根据指针实际指向的对象类型,调用对应的版本。这就是'调用同一函数,产生不同行为'的本质。
重写的细节
虚函数重写要求派生类函数与基类虚函数的返回值类型、函数名、参数列表完全一致。值得注意的是,派生类重写时可以不写 virtual 关键字,因为继承后基类的虚函数属性会保留,但为了代码规范,建议显式写出。
这里有一个经典的陷阱题,考察默认参数与虚函数重写的交互:
class A {
public:
virtual void func {
std::cout << << val << std::endl;
}
{
();
}
};
: A {
:
{
std::cout << << val << std::endl;
}
};
{
B* p = B;
p->();
;
}


