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

C++含模板抽象类的工厂模式设计问题求助

解决方案

核心问题是模板类的不同实例是完全独立的类型,Format<RGBData>和Format<PCMData>没有共同的非模板基类,因此无法用统一的指针类型返回。要实现工厂模式,需要先定义一个非模板的抽象基类作为所有格式类的统一接口。

步骤1:添加非模板抽象基类

在Formats内部定义不带模板的纯虚基类BaseFormat,保留所有格式类的公共接口:

class Formats {
public:
    // 非模板抽象基类,作为统一接口
    class BaseFormat {
    public:
        virtual bool writeFile() = 0;
        virtual ~BaseFormat() = default; // 必须定义虚析构,避免内存泄漏
    };

    // 模板类继承自BaseFormat,实现公共数据封装
    template <typename T>
    class Format : public BaseFormat {
    protected:
        GlobalHandleLock<T> lock;
    public:
        Format(HGLOBAL mediaData) : lock(mediaData) {} // 直接初始化成员更高效
        // 继承BaseFormat的纯虚函数,由派生类实现
        virtual bool writeFile() = 0;
    };

    // 改为public继承,否则工厂无法访问构造函数
    class BMPFormat : public Format<RGBData> {
    public:
        BMPFormat(HGLOBAL mediaData) : Format(mediaData) {}
        bool writeFile() override; // 实现BMP写入逻辑
    };

    class WAVFormat : public Format<PCMData> {
    public:
        WAVFormat(HGLOBAL mediaData) : Format(mediaData) {}
        bool writeFile() override; // 实现WAV写入逻辑
    };
};

步骤2:修改工厂类返回统一基类指针

工厂类现在可以返回Formats::BaseFormat*,所有具体格式类都兼容这个类型:

class FormatFactory {
public:
    Formats::BaseFormat* getFormat(const std::string& formatName, HGLOBAL mediaData) {
        if (formatName == "BMP") {
            return new Formats::BMPFormat(mediaData);
        } else if (formatName == "WAV") {
            return new Formats::WAVFormat(mediaData);
        }
        // 处理未知格式,返回nullptr或抛出异常
        return nullptr;
    }
};

调用方式

调用方无需关心模板类型,直接通过工厂获取对象并调用接口:

FormatFactory formatFactory;
HGLOBAL mediaData = ...; // 从剪贴板获取的数据
Formats::BaseFormat* format = formatFactory.getFormat("BMP", mediaData);
if (format) {
    format->writeFile();
    delete format; // 记得释放内存,或改用std::unique_ptr自动管理
}

关键说明

  • 虚析构函数:BaseFormat必须定义虚析构,否则通过基类指针删除派生类对象会触发未定义行为。推荐用std::unique_ptr替代裸指针,自动处理内存释放。
  • 继承权限:具体格式类必须public继承Format<T>,默认private继承会隐藏基类的public构造,导致工厂无法实例化对象。
  • 扩展性:后续新增格式时,只需添加对应的派生类,并在工厂的getFormat方法中新增分支即可,调用方代码无需修改。

内容的提问来源于stack exchange,提问作者tomysshadow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:31:01