题目
实现可扩展的图形面积计算器
信息
- 类型:问答
- 难度:⭐⭐
考点
继承设计,多态实现,纯虚函数,抽象类,动态绑定
快速回答
实现步骤:
- 创建抽象基类
Shape,声明纯虚函数calculateArea() - 派生
Circle和Rectangle类并重写虚函数 - 使用基类指针容器存储不同图形对象
- 通过虚函数机制实现多态调用
- 正确声明虚析构函数避免资源泄漏
原理说明
C++多态通过虚函数和动态绑定实现:
- 虚函数表(vtable):每个含虚函数的类拥有虚函数表,存储函数指针
- 动态绑定:运行时根据对象实际类型调用正确函数实现
- 纯虚函数强制派生类实现接口,形成抽象基类
代码实现
#include <iostream>
#include <vector>
#include <memory>
// 抽象基类
class Shape {
public:
virtual double calculateArea() const = 0; // 纯虚函数
virtual ~Shape() = default; // 虚析构函数
};
// 派生类 Circle
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
double calculateArea() const override {
return 3.14159 * radius * radius;
}
};
// 派生类 Rectangle
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double calculateArea() const override {
return width * height;
}
};
// 多态计算总面积
double totalArea(const std::vector<std::unique_ptr<Shape>>& shapes) {
double total = 0.0;
for (const auto& shape : shapes) {
total += shape->calculateArea(); // 动态绑定
}
return total;
}
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(5.0));
shapes.push_back(std::make_unique<Rectangle>(4.0, 6.0));
std::cout << "Total area: " << totalArea(shapes) << std::endl;
return 0;
}最佳实践
- 使用
override关键字明确表示重写虚函数 - 优先使用智能指针(
unique_ptr/shared_ptr)管理多态对象 - 为多态基类声明虚析构函数(规则:基类有虚函数则析构函数必须为虚)
- 接口类使用纯虚函数强制实现契约
常见错误
- 未将基类析构函数声明为虚函数 → 派生类资源泄漏
- 对象切片:尝试在容器中直接存储值类型而非指针/引用
- 忘记实现纯虚函数 → 导致抽象类实例化编译错误
- 误用
final关键字禁止进一步重写
扩展知识
- 动态绑定开销:虚函数调用比普通函数多一次指针解引用(访问vtable)
- RTTI(运行时类型识别):
typeid和dynamic_cast依赖虚函数表实现 - 性能优化:对性能关键路径,可考虑CRTP(奇异递归模板模式)实现静态多态
- 设计模式:多态是工厂模式、策略模式等的基础实现机制