You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++多态与动态类型转换实践困境及优化方案探讨

自研游戏引擎文件系统设计:多态与避免动态类型转换的难题

问题描述

游戏引擎中有多种对象(如Texture、Mesh等),均继承自Object类:

class Object
{
};

class Texture : public Object
{
};

我设计了用于存储对象的File类:

class File
{
public:
    Object* GetObject() const { return m_Object; }

private:
    Object* m_Object;
};

需要为存储特定类型对象的文件定义命令类FileCommand:

class FileCommand
{
public:
    virtual void Execute(File* file) = 0;
};

例如OpenFileInTextureEditorCommand类需要处理存储纹理的文件,此时必须将file->GetObject()返回的Object*转换为Texture*:

class OpenFileInTextureEditorCommand : public FileCommand
{
public:
    void Execute(File* file) override
    {
        Texture* texture = std::dynamic_cast<Texture*>(file->GetObject());
        if (texture)
        {
            // 在纹理编辑器中打开纹理...
        }
    }
};

解决方案

我设计的方案是把动态类型转换隐藏起来:
复用Object和Texture类,将File改为模板类,同时创建非模板基类FileBase以支持存入std::vector,File类负责处理动态类型转换:

class FileBase
{
public:
    Object* GetObject() const { return m_Object; }

protected:
    Object* m_Object = nullptr;
};

template<class T>
class File : protected FileBase
{
public:
    // 将类设为抽象类——无法实例化,仅负责处理动态类型转换
    virtual ~File<T>() = default;

    T* GetObject() const
    {
        // 隐藏的动态类型转换
        return dynamic_cast<T*>(m_Object);
    }
};

同样将FileCommand改为模板类,创建非模板基类FileCommandBase以支持存入std::vector,FileCommand类负责处理动态类型转换:

class FileCommandBase
{
public:
    virtual void Execute(FileBase* file) = 0;
};

template<class T>
class FileCommand : protected FileCommandBase
{
public:
    // 将类设为抽象类——无法实例化,仅负责处理动态类型转换
    virtual void Execute(File<T>* file) = 0;

protected:
    void Execute(FileBase* file) override
    {
        // 隐藏的动态类型转换
        Execute(dynamic_cast<File<T>*>(file));
    }
};

最终实现的OpenFileInTextureEditorCommand无需显式进行动态类型转换:

class OpenFileInTextureEditorCommand : public FileCommand<Texture>
{
public:
    void Execute(File<Texture>* file) override
    {
        Texture* texture = file->GetObject();
        if (texture)
        {
            // 在纹理编辑器中打开纹理...
        }
    }
};

总结

OpenFileInTextureEditorCommand的代码长度没变化,但逻辑更简洁。不过也发现了一些问题:

  • 动态类型转换的次数反而变多了,只是从显式变成了隐式
  • 新增了更多类,可能会提升维护难度

我可能过于执着于避免动态类型转换,但常听人说动态类型转换的存在是设计不佳的信号。

内容的提问来源于stack exchange,提问作者Anthony Blanchette-Potvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:10:24