侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

实现一个多态图形系统

2025-12-11 / 0 评论 / 4 阅读

题目

实现一个多态图形系统

信息

  • 类型:问答
  • 难度:⭐⭐

考点

继承机制,虚函数与多态,纯虚函数与抽象类,对象切片问题,智能指针使用

快速回答

实现一个图形绘制系统需要:

  • 定义抽象基类Shape,包含纯虚函数draw()area()
  • 派生CircleRectangle类并重写虚函数
  • 使用基类指针容器存储不同图形对象
  • 通过智能指针管理资源,避免内存泄漏
  • 遍历容器调用多态方法时需注意对象切片问题
## 解析

原理说明

多态允许通过基类接口操作不同派生类对象。在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_ptrstd::shared_ptr管理多态对象
  • 避免值传递多态对象,防止对象切片

常见错误

  • 对象切片:将派生类对象赋值给基类值类型变量,丢失派生类信息
  • 缺少虚析构函数:导致派生类资源泄漏
  • 未实现纯虚函数:使派生类仍为抽象类,无法实例化
  • 误用静态绑定:非虚函数在编译时绑定,无法实现多态

扩展知识

  • 动态类型识别:谨慎使用typeiddynamic_cast,通常表示设计缺陷
  • 协变返回类型:重写虚函数时可返回派生类指针/引用
  • final关键字:禁止类被继承或虚函数被重写
  • 虚函数表(vtable):编译器为实现多态生成的函数指针表