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

如何重载方法以接受const或non-const参数且避免代码重复

如何重载方法以接受const或non-const参数且避免代码重复

嘿,这个问题我太熟了——当你需要让方法同时支持const和非const的容器参数时,最烦的就是不想把一模一样的遍历逻辑写两遍。咱们来搞定它,既满足类型安全,又不重复代码。

首先,先看你的原始实现:现在的following方法只能接受非const的unordered_map,而且返回的是Foo*的vector。但如果碰到const的map,或者你需要返回const指针的vector时,这个方法就不够用了。直接写两个几乎一样的重载肯定不是最优解,咱们用模板提取核心逻辑的方式来解决。

第一步:把核心遍历逻辑抽成私有模板函数

我们可以写一个模板函数,它能处理任意类型的map(const或非const),然后根据传入的map类型自动推导返回的指针类型。把它设为私有,因为这只是实现细节,不需要对外暴露:

class Foo
{
    int* next;
    // 其他字段、方法...

    // 核心实现:模板函数处理不同类型的map
    template <typename MapType>
    auto following_impl(MapType& foos) const -> std::vector<
        typename std::conditional<
            std::is_const_v<std::remove_reference_t<MapType>>,
            const Foo*,
            Foo*
        >::type
    >
    {
        // 根据MapType是否为const,决定返回的指针类型
        using ResultPtr = typename std::conditional<
            std::is_const_v<std::remove_reference_t<MapType>>,
            const Foo*,
            Foo*
        >::type;

        std::vector<ResultPtr> result;
        const Foo* current = this;

        while (current->next)
        {
            auto nextIt = foos.find(*current->next);
            if (nextIt == foos.end()) break;

            // 这里会自动匹配const或非const的指针类型
            result.push_back(&nextIt->second);
            current = &nextIt->second;
        }

        return result;
    }

public:
    // 接下来写两个public的重载方法...
};

第二步:提供两个public重载接口

现在只需要写两个非常简短的public方法,分别对应const和非const的map参数,它们都会调用上面的模板实现:

// 非const版本:接受非const map,返回Foo*的vector
std::vector<Foo*> following(std::unordered_map<int, Foo>& foos)
{
    return following_impl(foos);
}

// const版本:接受const map,返回const Foo*的vector
std::vector<const Foo*> following(const std::unordered_map<int, Foo>& foos) const
{
    return following_impl(foos);
}

为什么这么做?

  • 避免代码重复:所有的遍历、查找逻辑都只在following_impl里写一遍,两个重载只是做类型适配。
  • 类型安全:传入const map时,自动返回const指针的vector,不会出现意外的可修改指针;传入非const map时,返回可修改的指针,符合预期。
  • 兼容性:如果用的是C++14,把std::is_const_v换成std::is_const<typename std::remove_reference<MapType>::type>::value,std::remove_reference_t换成typename std::remove_reference<MapType>::type就行,同样能正常工作。

使用示例

// 非const容器场景
std::unordered_map<int, Foo> foos;
// 填充foos...
Foo& myFoo = foos[1];
std::vector<Foo*> nonConstFollowers = myFoo.following(foos);

// const容器场景
const std::unordered_map<int, Foo>& constFoos = foos;
const Foo& constMyFoo = constFoos.at(1);
std::vector<const Foo*> constFollowers = constMyFoo.following(constFoos);

这样不管你手里是const还是非const的map,都能调用对应的following方法,而且完全不用重复写遍历代码,完美解决你的问题!

备注:内容来源于stack exchange,提问作者Bruce Nielsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 13:38:01