关于分层结构的一般建议

General advice on hierarchical structs

本文关键字:结构 于分层 分层      更新时间:2023-10-16

编辑:我将保留我最初发布的问题的第一部分,尽管我现在可以看到我在最后的问题措辞不好。我总是从字面上理解每件事,有时别人不这么做会让我感到惊讶。我知道那是我自己的缺点。我试图重新表述这些问题,希望能更好地传达我实际上在寻找什么样的答案。

我首先要说的是,由于我在一个非常小的项目中工作,因此实际的执行可能并不重要,但我一直高度重视理论,因此我从一开始就养成了正确的习惯,因此我往往会陷入无关紧要的地方。不过,让我们假装这很重要。我很想知道在这种情况下我有不同选择的利弊。

我正在做一个程序,你可以根据自己的喜好定制环境。这种环境的设置称为配置文件。您可以在多个配置文件之间切换,并且一次只能激活一个配置文件。

我可能想要在将来更新程序,这意味着我可能会尝试加载过时的配置文件格式,其中某些设置缺失。为了使事情对我自己更容易,并确保向后兼容性,我决定做一个名为ProfileManager的类,它将加载配置文件格式并在必要时更新它们。

我还决定制作一个struct Profile,它将保留所有设置,这就是我的问题出现的地方。

请看我试用过的三个版本:

struct Profile
{
    // Version one: lots of variables with closely related names
    bool window_one_open;
    bool window_one_collapsed;
    int window_one_pos_x;
    int window_one_pos_y;
    int window_one_width;
    int window_one_height;
    // Version two: named structs used to easily create multiple entries of the same format
    struct position
    {
        int x;
        int y;
    };
    struct window
    {
        bool open;
        bool collapsed;
        position pos;
        int width;
        int height;
    };
    window color_palette;
    window text_editor;
    window browser;
    // Version three: unnamed struct(s) used to simply group certain variables together
    struct
    {
        bool some_setting;
        bool some_other_setting;
        int important_number;
    } general_settings;
};

版本1很简单,我确信它在性能和内存使用方面比版本2和版本3得分更高(如果有任何区别的话)。但是,这些名称可能会变得非常长,而且我不喜欢长标识符。

在版本2中,我可以使用更短的标识符,我真的宁愿使用profile.color_palette.pos.x而不是profile.color_palette_pos_x来标识属性。不过有一个缺点。当我输入profile.时,它建议window不是一个属性,而是一个结构体,当我不直接在profile.h内部工作时,我没有使用它。

版本3解决了我在版本1和2中遇到的问题,但它引入了一个新问题。当我输入profile.时,它提示some_setting,我不应该通过profile访问,只能通过profile.general_settings。这只是Code::Blocks很奇怪,还是有什么我不知道的基本知识?

所以我的问题是(改写):

  • 使用我的任何样本结构客观上是一个错误的选择吗?也就是说,它们中的任何一个在性能方面比其他的稍微差一点吗?与版本1相比,嵌套结构是否使用了过多的内存?是否有哪个版本比其他版本更容易出现bug ?我只是在这里寻找是或否的答案,这样我就知道我选择其中任何一个是不明智的。也许,在决定使用结构时,我应该记住其他一些事情吗?
  • 在决定是否使用嵌套结构时,是否有任何不成文的规则或一些常识?再一次,我只是在这里寻找一个是或不是。
  • 是否有任何命名约定,人们希望我使用嵌套结构(如类被命名为LikeThis和getter和setter通常被命名为like_this)?我应该在我打算使用它们的作用域内部还是外部声明它们?我读到人们通常建议不要在不必要的情况下扩大范围,我只是想确定一下,因为我以前从未在一个建议甚至合法的环境中工作过。
  • 在这种情况下,是否存在一种结构在客观上优于其他结构?(它可能是我甚至没有想到的东西)

不,这完全取决于你的实际用例,以及如何更好地解决它们

  • 嵌套结构(至少,嵌套结构声明)似乎引入了比它们解决的更多的问题,并且它们大大降低了可读性,所以我的直觉告诉我应该避免它。关于这一点的普遍共识是什么?

嵌套结构本身有它们的用例,大多数情况下,如果嵌套结构/类与声明的外部类/结构紧密耦合(例如,像标准容器迭代器类与它们相关的容器实现耦合)。如果没有这样紧密的耦合关系,使用它们会使事情变得复杂,是的。

  • 如果我使用嵌套结构体,我应该使用结构体或变量的命名约定吗?我应该在我打算使用它们的作用域内部还是外部声明它们?

除了为了与c++标准类的模板参数兼容,我想没有特殊的命名约定。如果你有这样一个嵌套的iterator类定义,那么就这样命名它,并按照标准算法和其他操作的要求完成契约。

正如在示例#2中所指出的那样,似乎接口(在您的类之外声明的)可能更适合组装您需要的这种关系和抽象
struct IPosition {
    virtual int x() const = 0;
    virtual int y() const = 0;
    virtual ~IPosition() {}
};
struct IWindow {
    virtual bool open() const = 0;
    virtual bool collapsed() const = 0;
    virtual const IPosition& pos() const = 0;
    virtual int width() const = 0;
    virtual int height() const = 0;
    virtual ~IWindow() {}
};
struct Profile {
    IWindow& windowOne;
    IWindow& windowTwo;
    // Provide an appropriate IWindow implementation instances 
    // when constructing here
    Profile(IWindow& windowOne_, IWindow& windowTwo_) 
    : windowOne(windowOne_)
    , windowTwo(windowTwo_)
    {}
};