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

C++中使用unordered_set/map时如何实现类的良好封装?

问题解答

是否可以将struct改为class并添加对应成员

是可以实现的,仅需要解决两个核心编译限制:

  1. 自定义哈希函数HashFunction需要访问Node类的私有成员val,可以通过友元声明或者新增公有getter方法解决
  2. 类内定义持有自身类型的unordered_set属于不完整类型使用,C++17及以上版本的标准库实现普遍支持该用法,低版本标准可以改用智能指针包装元素避免编译错误

修改后的可运行代码如下:

#include <iostream>
#include <unordered_set>
using namespace std;

// 前置声明Node类
class Node;
class HashFunction{
public:
    size_t operator()(const Node& n) const;
};

class Node{
private:
    int val;
    // 声明哈希函数为友元,允许访问私有val
    friend class HashFunction;
    unordered_set<Node, HashFunction> neighbours;
public:
    Node(int v) : val(v) {}

    bool operator==(const Node& n) const{
        return this->val == n.val;
    }

    // 封装邻居操作的成员方法,避免直接暴露内部集合
    void add_neighbour(const Node& n) {
        neighbours.insert(n);
    }

    int get_val() const {
        return val;
    }

    const unordered_set<Node, HashFunction>& get_neighbours() const {
        return neighbours;
    }
};

// 哈希函数的实现要放在Node类定义之后
size_t HashFunction::operator()(const Node& n) const{
    return n.val;
}

int main(){
    Node n1(1), n2(2), n3(3), n4(4);
    n1.add_neighbour(n2);
    n1.add_neighbour(n3);

    unordered_set<Node, HashFunction> us;
    us.insert(n1);
    us.insert(n2);
    us.insert(n3);
    us.insert(n4);
    
    for (const auto& node : us){
        cout << node.get_val() << " ";
    }
    cout << endl;

    cout << "n1的邻居:";
    for (const auto& neighbour : n1.get_neighbours()) {
        cout << neighbour.get_val() << " ";
    }
    cout << endl;
    return 0;
}

保证封装性的最佳实践

  • 优先用公有getter替代友元:如果不想将哈希函数设为友元,可以给Node类新增公有的get_val()方法,哈希函数直接调用公有方法读取值即可,耦合度更低,也不会破坏封装性
  • 兼容低版本标准的不完整类型处理:如果使用C++17以下标准,无法直接在类内定义unordered_set<Node>,可以将容器元素改为std::shared_ptr<Node>,既解决不完整类型编译错误,也能避免存储完整对象带来的拷贝开销和对象切片问题
  • 哈希计算和判等逻辑对齐:所有参与operator==判断的成员字段,都要纳入哈希值的计算逻辑,避免大量哈希冲突降低unordered_set的性能,多字段哈希可以用std::hash组合各个字段的哈希值
  • 不直接暴露内部容器成员:不要把neighbours设为公有,也不要返回非const的引用给外部,提供专门的增删查成员方法操作内部集合,保证内部状态的修改都在类的控制范围内
  • 判等函数加const限定:operator==必须声明为const成员函数,保证unordered_set内部调用时可以操作const的Node对象

内容的提问来源于stack exchange,提问作者Firat Cem Gurbey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 05:15:02