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

扩展std::vector时,该选择组合还是继承?

方案选择建议:组合优先,搭配适配层兼顾易用性

你的核心需求是必须保证所有元素都经过解析流程,无法直接篡改或添加未解析内容,基于这个优先级最高的要求,我们来分析两种方案的适配性,并给出更优实现:

为何不推荐继承std::vector

继承方案的隐患远大于便利:

  • 你需要逐一删除或重写std::vector所有能直接修改内部的接口,包括10+个构造函数、emplace/insert/push_back等修改方法,甚至非const的operator[],工作量极大。
  • 若后续C++标准库给vector新增修改类方法,你的类会直接出现漏洞——用户可以通过新方法绕过解析规则,完全违背你的设计初衷。
  • 语义上,你的query2并非"vector的扩展",而是"基于解析规则的路径容器",继承会模糊这个核心定位。

组合方案的优化实现

组合是更贴合需求的选择,它能完全控制对外接口,同时通过适配层复用vector的特性,避免重复造轮子:

示例实现

#include <vector>
#include <string_view>
#include <algorithm>

struct Query {
    // 仅允许从字符串解析构造
    explicit Query(std::string_view path) {
        parse(path);
    }

    // 赋值操作也必须走解析流程
    Query& operator=(std::string_view path) {
        str_.clear();
        parse(path);
        return *this;
    }

    // 暴露只读迭代器,复用vector的迭代器逻辑
    auto begin() const noexcept { return str_.begin(); }
    auto end() const noexcept { return str_.end(); }
    auto cbegin() const noexcept { return str_.cbegin(); }
    auto cend() const noexcept { return str_.cend(); }

    // 只读元素访问
    const std::string_view& operator[](size_t idx) const noexcept { return str_[idx]; }
    const std::string_view& at(size_t idx) const { return str_.at(idx); }

    // 常用容器属性
    size_t size() const noexcept { return str_.size(); }
    bool empty() const noexcept { return str_.empty(); }

    // 安全转换为const vector引用,兼容接受vector的函数
    const std::vector<std::string_view>& as_vector() const noexcept { return str_; }

private:
    std::vector<std::string_view> str_;

    // 核心解析逻辑:按'/'分割路径
    void parse(std::string_view path) {
        // 跳过开头的'/'
        if (!path.empty() && path.front() == '/') {
            path = path.substr(1);
        }

        size_t pos = 0;
        while (pos < path.size()) {
            const size_t next_slash = path.find('/', pos);
            if (next_slash == std::string_view::npos) {
                str_.push_back(path.substr(pos));
                break;
            }
            str_.push_back(path.substr(pos, next_slash - pos));
            pos = next_slash + 1;
        }
    }
};

组合方案的优势

  • 完全可控:所有外部修改都必须经过解析函数,彻底杜绝绕过规则的可能,哪怕std::vector后续新增方法也不会影响。
  • 低重复开发:直接复用vector的迭代器、元素访问逻辑,仅需实现解析核心和必要的适配接口。
  • 语义清晰:类的定位明确为"路径解析容器",其他开发者能快速理解其用途和限制。
  • 兼容现有代码:通过as_vector()方法可以安全地将内部数据传递给接受const vector的函数,同时保证外部无法修改。

总结

你的场景下组合方案是最优选择,它完美契合"数据必须经过解析、不可篡改"的核心需求,同时通过适配层兼顾了std::vector的易用性。继承方案因存在不可控的安全隐患和高昂的维护成本,并不适合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:10:13