MST

星途 面试题库

面试题:C++类与对象设计原则在复杂系统中的应用及内存管理

设计一个简单的游戏场景管理系统,包含`GameObject`基类,以及`Player`、`Enemy`、`Obstacle`等派生类。要求遵循C++类与对象的设计原则,如单一职责原则、开闭原则等。同时,在系统中会频繁创建和销毁游戏对象,描述并实现一种有效的内存管理策略,以避免内存泄漏和提高系统性能,说明在整个设计过程中如何体现类与对象设计原则。
29.7万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 类设计

  1. GameObject基类

    class GameObject {
    public:
        virtual void update() = 0;
        virtual void draw() = 0;
        virtual ~GameObject() = default;
    };
    
    • 这里体现了单一职责原则,GameObject基类只负责定义所有游戏对象共有的行为接口,如updatedraw,每个具体的游戏对象类只需要关注自己特定的更新和绘制逻辑。
  2. Player派生类

    class Player : public GameObject {
    private:
        int health;
        int score;
    public:
        Player() : health(100), score(0) {}
        void update() override {
            // 玩家更新逻辑,如根据输入移动等
        }
        void draw() override {
            // 绘制玩家的逻辑
        }
    };
    
    • Player类遵循单一职责原则,只负责玩家相关的属性和行为,如生命值、分数以及玩家的更新和绘制。
  3. Enemy派生类

    class Enemy : public GameObject {
    private:
        int health;
        int damage;
    public:
        Enemy() : health(50), damage(10) {}
        void update() override {
            // 敌人更新逻辑,如AI移动等
        }
        void draw() override {
            // 绘制敌人的逻辑
        }
    };
    
    • 同样,Enemy类专注于敌人特有的属性和行为,符合单一职责原则。
  4. Obstacle派生类

    class Obstacle : public GameObject {
    private:
        int positionX;
        int positionY;
    public:
        Obstacle(int x, int y) : positionX(x), positionY(y) {}
        void update() override {
            // 障碍物更新逻辑,可能无需更新
        }
        void draw() override {
            // 绘制障碍物的逻辑
        }
    };
    
    • Obstacle类负责管理障碍物的位置及相关绘制和更新逻辑,体现单一职责原则。

2. 内存管理策略

  1. 智能指针:使用std::unique_ptrstd::shared_ptr来管理游戏对象的内存。例如,在场景管理类中,可以使用std::vector<std::unique_ptr<GameObject>>来存储所有游戏对象。
    #include <memory>
    #include <vector>
    
    class SceneManager {
    private:
        std::vector<std::unique_ptr<GameObject>> gameObjects;
    public:
        void addGameObject(std::unique_ptr<GameObject> obj) {
            gameObjects.push_back(std::move(obj));
        }
        void removeGameObject(size_t index) {
            if (index < gameObjects.size()) {
                gameObjects.erase(gameObjects.begin() + index);
            }
        }
        void updateAll() {
            for (auto& obj : gameObjects) {
                obj->update();
            }
        }
        void drawAll() {
            for (auto& obj : gameObjects) {
                obj->draw();
            }
        }
    };
    
    • 这种方式体现了开闭原则,在不修改现有代码结构的情况下,可以方便地添加新的游戏对象类型。例如,如果要添加一个新的PowerUp类,只需要创建PowerUp类继承自GameObject,然后使用SceneManageraddGameObject方法添加即可。同时,智能指针自动管理内存,避免了手动释放内存可能导致的内存泄漏问题,提高了系统性能。

3. 总结

  • 单一职责原则:每个类只负责一种职责,GameObject基类定义通用接口,派生类实现各自特定的行为,使得代码结构清晰,易于维护和扩展。
  • 开闭原则:通过智能指针管理内存的场景管理系统,在不修改现有类的代码的情况下,可以方便地添加新的游戏对象类型,符合开闭原则,保证了系统的可扩展性。