题目
实现一个多态图形系统
信息
- 类型:问答
- 难度:⭐⭐
考点
继承机制,虚函数与多态,纯虚函数与抽象类,对象切片问题,智能指针使用
快速回答
实现一个图形绘制系统需要:
- 定义抽象基类
Shape,包含纯虚函数draw()和area() - 派生
Circle和Rectangle类并重写虚函数 - 使用基类指针容器存储不同图形对象
- 通过智能指针管理资源,避免内存泄漏
- 遍历容器调用多态方法时需注意对象切片问题
原理说明
多态允许通过基类接口操作不同派生类对象。在C++中通过虚函数实现:
- 虚函数:使用
virtual关键字声明,派生类可重写 - 纯虚函数:在基类中声明为
virtual ... = 0,使类成为抽象类 - 动态绑定:运行时根据对象实际类型调用正确函数
代码示例
#include <iostream>
#include <vector>
#include <memory>
// 抽象基类
class Shape {
public:
virtual void draw() const = 0; // 纯虚函数
virtual double area() const = 0;
virtual ~Shape() = default; // 虚析构函数
};
// 派生类 Circle
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
void draw() const override {
std::cout << "Drawing Circle with radius: " << radius << std::endl;
}
double area() 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) {}
void draw() const override {
std::cout << "Drawing Rectangle " << width << "x" << height << std::endl;
}
double area() const override {
return width * height;
}
};
// 多态处理函数
void processShapes(const std::vector<std::unique_ptr<Shape>>& shapes) {
for (const auto& shape : shapes) {
shape->draw();
std::cout << "Area: " << shape->area() << "\n\n";
}
}
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));
processShapes(std::move(shapes));
return 0;
}最佳实践
- 为多态基类声明虚析构函数,确保正确释放资源
- 使用
override关键字明确表示重写虚函数 - 优先使用
std::unique_ptr或std::shared_ptr管理多态对象 - 避免值传递多态对象,防止对象切片
常见错误
- 对象切片:将派生类对象赋值给基类值类型变量,丢失派生类信息
- 缺少虚析构函数:导致派生类资源泄漏
- 未实现纯虚函数:使派生类仍为抽象类,无法实例化
- 误用静态绑定:非虚函数在编译时绑定,无法实现多态
扩展知识
- 动态类型识别:谨慎使用
typeid和dynamic_cast,通常表示设计缺陷 - 协变返回类型:重写虚函数时可返回派生类指针/引用
- final关键字:禁止类被继承或虚函数被重写
- 虚函数表(vtable):编译器为实现多态生成的函数指针表