【问题标题】:Private set / get functions -- Why private and how to use?私有设置/获取函数——为什么私有以及如何使用?
【发布时间】:2011-11-02 10:13:37
【问题描述】:

我阅读了很多指南,解释了为什么我应该使用“私人”,而答案总是“因为我们不希望其他人将其设置为某事”。所以,让我问以下问题:

假设我想要一个设置一次的变量(可能类似于视频游戏中的角色名称,询问一次,然后设置它,然后您只需使用 get 变量(编辑:函数)游戏的其余部分)我如何处理那一组?我将如何处理这个获取?

在这种情况下使用私有访问修饰符的实际优势是什么?如果我从不提示用户再次输入名称,并且从不将信息存储回 class.name,那么数据不应该保持安全(适度,假设代码按预期工作)吗?

我希望有人能帮助我解决这个问题,因为我在这里搜索和看到的解释并没有完全让我的想法休息。

谢谢!

【问题讨论】:

  • 查看我仍在尝试阅读的设计原则书,主要是解耦问题。即使在一个对象内,最好确保没有单位对任何其他单位了解太多。
  • Getter 和 setter 是完全错误的 OO 尝试。不要使用它们。他们使quasi classes

标签: c++ access-modifiers


【解决方案1】:

当有问题的数据涉及多个变量时,私有 getter 和 setter 都有意义,有您希望确保遵守的其他约束,并且这些操作在您的班级中完成了多次。或者当您计划对数据模型进行进一步修改并希望对数据进行抽象操作时,例如使用 std::vector 但计划使其成为 std::map 或类似情况。

举个个人例子,我有一个智能指针实现,它带有一个私有的 reset(T*, int*) 方法,它本质上是存储对象及其引用计数的设置器。它处理检查对象和引用计数的有效性,增加和减少引用计数,以及删除对象和引用计数。它在类中被调用了八次,因此将它放入一个方法中是非常有意义的,而不是每次都使用成员变量,从而减慢编程速度、使代码臃肿并冒着过程中出错的风险。

如果您从模型中抽象数据和/或您必须实施错误检查,例如如果数据为 NULL 而不是返回 NULL,则抛出指令,我相信私有 getter 也很有意义。

【讨论】:

    【解决方案2】:

    如果变量是“一次写入,然后永远只读”,我建议将其设为const 成员,并在构造过程中进行初始化。私有“setter”函数没有任何价值,因为它不会被使用。此外,您还可以避免人们使用 setter 函数来设置名称,因为它永远不会被设置。

    例如:

    class Player
    {
      private:
        const std::string m_name;
    
      public:
        Player(const std::string& name) : m_name(name) {}
     };
    

    【讨论】:

    • const 成员存在问题,它会阻止您的对象被复制分配。这意味着您不能将其放入 std::vector (或一堆其他 std 容器)中。
    【解决方案3】:

    不要混淆类的 privatepublic 接口。从理论上讲,它们是完全不同的接口,这只是 C++ 的一个设计特性,它们在物理上位于同一个类声明中。

    当对象属性应该通过公共接口公开时,使用公共 getter/setter 是完全可以的,因此没有诸如“setter 始终是私有的”之类的规则。

    Herb Sutter 撰写的 (More) Exceptional C++ 书籍中有关该主题的更多信息。对于想要了解 C++ 并精通 C++ 的人来说,这是一本绝对必要的读物。

    如果您对决定是否在类变量上使用 getter/setter 有疑问,互联网上有很多解释为什么 getter/setter 更好。

    【讨论】:

      【解决方案4】:

      访问说明符主要用于表示类接口,而不是有效地限制程序员的访问或保护事物。它们用于防止意外黑客攻击。

      如果设置了一次,那么你应该在创建时尝试设置它,并使其成为const

      如果界面不需要特别清晰(例如,如果很少有人需要学习它),那么花精力设计它是没有意义的。此外,对界面使用的方式没有太大影响的更改可以在以后应用。可以使用简单的搜索和替换将公开的变量更改为 getter/setter。

      如果它是一个已发布的二进制接口,那么您会希望第一次就做好。但是您只是在谈论程序的内部结构。

      而且任何人都不太可能意外重置玩家名称。

      【讨论】:

        【解决方案5】:

        我不会试图证明私有 set 方法的合理性,因为这对我来说听起来有点奇怪。您可以使用朋友声明来处理一组。但是既然朋友可以直接设置值,为什么还要定义一个setter呢?

        如果我可以管理它,我通常会避免使用二传手。相反,我更喜欢提供通过构造函数设置成员变量的工具。如果它们有意义,我很乐意提供 getter。

        class player_character_t {
            std::string name_;
        public:
            player_character_t(std::string const& name)
            :   name_ (name)
            {
            }
        
            std::string const& name() const { return name_; }
        };
        

        这会迫使您延迟对象的构建,直到您获得所需的所有信息。它简化了对象的逻辑(即它们有一个简单的状态图),并且意味着您不必在读取之前检查是否设置了某些内容(如果对象存在,则设置正确)。

        http://en.wikipedia.org/wiki/State_diagram

        将内容标记为私有有助于防止发生意外。因此,当您犯了错误并且“代码按预期工作”不再是这种情况时,编译器可能会帮助您检测到它。同样, const 可以在您错误地使用对象时提供很大帮助。

        【讨论】:

          【解决方案6】:

          最后一个括号很重要:假设代码按预期工作。

          在我看来,它类似于 Linux 系统中的权限。您知道 root 密码并且可以删除任何文件,但您不会以 root 身份保持登录状态,因此您不会意外执行任何操作。类似地,当你有一个私有变量 characterNameString,而后来有人(或你)试图给它一个新值时,它会失败。该人将不得不查看代码并查看它是否已标记为私有。那个人将不得不问自己“为什么这是私人的?我应该修改它吗?我应该以另一种方式这样做吗?”如果他们决定他们想要,那么,他们可以。但它可以防止愚蠢的错误。

          【讨论】:

          • 真的只有这个原因吗?
          • 我认为这是主要原因。考虑一下您是否编写了 SuperFreeProj 开源项目。假设你在那个项目中有一个班级扶手椅。您可能希望通过修改某些成员的工作方式来改变 Armchair 的工作方式。如果它们是私有的,那么您知道使用您的项目的任何人都不会在更新时注意到它们。如果它们是公开的,则可能有人编写了依赖于这些成员的代码,并且该代码会损坏,他们会感到难过。
          猜你喜欢
          • 2010-10-12
          • 1970-01-01
          • 2019-10-15
          • 2010-10-09
          • 1970-01-01
          • 1970-01-01
          • 2010-11-11
          • 2011-05-29
          • 2011-12-06
          相关资源
          最近更新 更多