用public继承封装跨平台本地数据存储基类,核心是抽象共性、隔离差异、保持接口一致:基类定义纯虚接口和保护工具方法,子类仅实现平台相关IO,通过工厂按编译宏创建对应实例。

用 public 继承封装跨平台本地数据存储基类,核心是抽象共性、隔离差异、保持接口一致。不是堆功能,而是搭骨架——让后续 iOS/Android/Windows/macOS 等平台子类只专注实现底层读写,不重复处理序列化、错误包装、线程安全等通用逻辑。
一、定义清晰的基类接口(纯虚+保护成员)
基类不负责具体存哪、怎么存,只约定“能做什么”和“该注意什么”:
class DataStorageBase {
protected:
// 存储路径由子类在构造时传入并管理(平台相关)
std::string m_storagePath;
// 可选:统一的日志/错误回调,供子类触发
std::function<void(const std::string&)> m_errorHandler;
// 保护方法:供子类调用的通用工具(如 JSON 序列化/反序列化)
bool serializeToJson(const nlohmann::json& data, std::string& outStr);
bool deserializeFromJson(const std::string& inStr, nlohmann::json& outData);
public:
explicit DataStorageBase(const std::string& path) : m_storagePath(path) {}
virtual ~DataStorageBase() = default;
// 核心能力:读、写、删、查存在
virtual bool write(const std::string& key, const nlohmann::json& value) = 0;
virtual bool read(const std::string& key, nlohmann::json& outValue) = 0;
virtual bool remove(const std::string& key) = 0;
virtual bool exists(const std::string& key) = 0;
// 可选:批量操作、清空、统计等(也可留空或默认实现)
virtual size_t count() { return 0; }
virtual void clear() = 0;
};✅ 关键点:
- 所有
public接口为虚函数,强制子类实现;protected工具方法(如 JSON 处理)避免重复造轮子;- 不暴露文件句柄、数据库连接等平台细节;
- 错误通过回调或返回值传递,不抛异常(便于跨平台异常模型兼容)。
二、用 public 继承派生各平台实现类
public 继承确保“is-a”语义成立:FileStorageLinux 是一个 DataStorageBase,可安全向上转型,支持多态调用。
// Linux/macOS:基于文件系统 + JSON 文件
class FileStoragePOSIX : public DataStorageBase {
private:
std::mutex m_mutex; // 保护文件读写并发
protected:
std::string getKeyFilePath(const std::string& key) const {
return m_storagePath + "/" + key + ".json";
}
public:
explicit FileStoragePOSIX(const std::string& path) : DataStorageBase(path) {
// 确保目录存在
std::filesystem::create_directories(m_storagePath);
}
bool write(const std::string& key, const nlohmann::json& value) override {
std::lock_guard<std::mutex> lock(m_mutex);
std::string jsonStr;
if (!serializeToJson(value, jsonStr)) return false;
std::ofstream f(getKeyFilePath(key));
if (!f.is_open()) return false;
f << jsonStr;
return f.good();
}
bool read(const std::string& key, nlohmann::json& outValue) override {
std::lock_guard<std::mutex> lock(m_mutex);
std::ifstream f(getKeyFilePath(key));
if (!f.is_open()) return false;
std::string content((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
return deserializeFromJson(content, outValue);
}
// ... 其他方法实现
};// Windows:可用 WinRT `ApplicationData` 或 `std::filesystem`
class FileStorageWinRT : public DataStorageBase {
// 同样继承 public,复用基类工具,只重写底层 IO
};✅ 关键点:
- 每个子类只写真正平台相关的代码(路径规则、API 调用、权限检查);
- 自动获得基类的 JSON 工具、错误处理框架、线程保护骨架;
- 外部代码只需依赖
DataStorageBase*,完全解耦平台细节。
三、配合工厂或配置实现运行时切换
避免硬编码平台分支,用简单工厂统一创建:
std::unique_ptr<DataStorageBase> createStorage(const std::string& basePath) {
#if defined(_WIN32)
return std::make_unique<FileStorageWinRT>(basePath);
#elif defined(__linux__) || defined(__APPLE__)
return std::make_unique<FileStoragePOSIX>(basePath);
#else
static_assert(false, "Unsupported platform");
#endif
}
// 使用示例
auto storage = createStorage("/data/local");
storage->write("user_prefs", {{"theme", "dark"}, {"lang", "zh"}});✅ 关键点:
- 编译期分发,零运行时开销;
- 新增平台只需加一个
#elif分支和对应子类;- 基类不变,所有扩展不破坏原有逻辑。
不复杂但容易忽略:基类里不写一行平台 API,子类里不重复处理 JSON 或加锁逻辑——这才是 public 继承在跨平台封装中最优雅的落点。

















