题目
理解C++中的多态行为
信息
- 类型:问答
- 难度:⭐
考点
虚函数,继承,多态原理
快速回答
当基类指针指向派生类对象时:
- 若函数声明为虚函数(virtual),调用时执行派生类的实现(动态绑定)
- 若函数未声明为虚函数,调用时执行基类的实现(静态绑定)
代码示例中:
- speak()是虚函数:输出"Meow!"
- eat()非虚函数:输出"Animal eats"
原理说明
C++多态通过虚函数机制实现:
- 虚函数:使用
virtual关键字声明,运行时根据对象类型决定调用哪个函数 - 虚函数表(vtable):每个含虚函数的类拥有一个vtable,存储函数指针
- 动态绑定:通过基类指针/引用调用虚函数时,在运行时查找vtable确定实际调用的函数
代码示例
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() { cout << "Animal sound" << endl; }
void eat() { cout << "Animal eats" << endl; }
};
class Cat : public Animal {
public:
void speak() override { cout << "Meow!" << endl; } // 重写虚函数
void eat() { cout << "Cat eats fish" << endl; } // 隐藏基类函数
};
int main() {
Animal* animal = new Cat();
animal->speak(); // 输出: Meow! (多态)
animal->eat(); // 输出: Animal eats (非多态)
delete animal;
return 0;
}关键行为分析
- speak()调用:虚函数,实际调用Cat::speak()(动态绑定)
- eat()调用:非虚函数,根据指针类型调用Animal::eat()(静态绑定)
常见错误
- 忘记将基类函数声明为
virtual,导致无法实现多态 - 派生类函数签名不一致(如const修饰不同),导致意外创建新函数而非重写
- 未将基类析构函数声明为虚函数,导致派生类资源泄漏
最佳实践
- 对需要多态的函数始终使用
virtual关键字 - C++11+中使用
override关键字明确表示重写(编译器会检查签名) - 基类析构函数必须声明为虚函数(
virtual ~Animal() = default;)
扩展知识
- final关键字:禁止派生类重写虚函数(
virtual void speak() final {...}) - 纯虚函数:
virtual void speak() = 0;使类成为抽象基类 - 动态类型识别:
dynamic_cast<Cat*>(animal)可在运行时检查类型