在 c++ 中使用 unordered_set/map 时如何制作封装良好的类?

Posted

技术标签:

【中文标题】在 c++ 中使用 unordered_set/map 时如何制作封装良好的类?【英文标题】:How to make well-encapsulated classes while using unordered_set/map in c++? 【发布时间】:2021-07-05 17:18:37 【问题描述】:

我正在查看一些关于如何为类/结构制作 unordered_set 的教程。我发现这个易于理解的代码(作为 Java 开发人员)可以解决问题:

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

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

class HashFunction
    public:
        size_t operator()(const Node& n) const
            return n.val;
        
;

int main()
    Node n1 =  1 , n2 =  2 ,
         n3 =  3 , n4 =  4 ;

    unordered_set<Node, HashFunction> us;
    us.insert(n1);
    us.insert(n2);
    us.insert(n3);
    us.insert(n4);
    
    for (auto node : us)
        cout << node.val << " ";
    
    cout << endl;
    return 0;

我想知道我们是否可以将struct Node 设为类,将int val 设为私有字段并将unordered_set&lt;Node, HashFunction&gt; neighbours 作为字段添加到Node 类。

如果没有,保持类/结构良好封装并为类设置集合/映射字段的良好做法是什么?

【问题讨论】:

请注意,C++ 中的 Node 表示实际对象,而不是 Java 中的指针。 “邻居”集合需要多对多关系,只能用指针来实现。 Struct 只是一个默认对所有成员公开的类。如果您将 val 设为私有,则类 Hash 无法返回它。 @BenVoigt 感谢您的评论,您的意思是“邻居”集应该有一个 Node* 作为模板吗? @sucksatnetworking 感谢您的评论。我现在将尝试使“节点”成为一个类。 【参考方案1】:

这里有几个问题,所以我会尝试按顺序回答:

可以使struct Node 成为一个类

是的,structclass 仅在它们的默认权限上有所不同(在 struct 中,除非另有说明,否则在 class 中它们是 private) 所以这和你写的代码是一样的:

class Node
public:
    int val;
  
    bool operator==(const Node& n) const
        return (this->val == n.val);
    
;

int val 设为私有字段并将unordered_set&lt;Node, HashFunction&gt; neighbours 作为字段添加到Node

是的,你可以。我能想到的从您编写的代码进行转换的最简单方法是使HashFunction 成为Node 的子类。 例如:

class Node 
    class HashFunction 
        public:
            size_t operator()(const Node& n) const
                return n.val;
            
    ;

public:
    Node(int _val) : val(_val) 

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

    // More methods here

private:
    int val;
    unordered_set<Node, HashFunction> neighbours;
;

如果没有,保持类/结构良好封装并为类设置集合/映射字段的良好做法是什么?

我想在这种情况下这是一个无声的问题 - 但一般的答案是只公开最低要求的接口。例如,现在HushFunction 知道Node 的内部内容。为了增加封装,我们可以向Node 添加一个hush 方法,并让HushFunction 调用该方法。这样,如果Node 的内容发生变化,Node 之外的任何内容都不需要注意。

【讨论】:

以上是关于在 c++ 中使用 unordered_set/map 时如何制作封装良好的类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual C++ 2010 中使用 C++ 库 [重复]

我们啥时候需要在纯 C++ 程序中使用结构?纯 C++ 程序是不是需要结构? [复制]

当python使用“Python.h”调用该c++进程时,如何在python中停止一个c++进程

在 Objective-C 中使用外部 C++ 头文件

使用多个视图在 QML 中查看、编辑和更新数据(来自 C++),而数据保留在 C++ 中(订阅数据)

在 c++ 应用程序中使用 Simulink