【问题标题】:Does it make sense to provide non-const reference getter提供非常量引用 getter 是否有意义
【发布时间】:2011-05-06 01:23:37
【问题描述】:

有时我需要公开一些班级成员。例如在下面的例子中class Mechanic 可能需要直接访问Engine 组件。我读过很多次,由于几个原因,所有字段都应该由 mutator(访问器)方法访问。但是在提供非常量引用 getter 时有什么好处:

class Car
{
    public:
        Engine & engine()
        {
           return m_engine;
        }

        //as a consequence you will also need to provide const version
        const Engine & engine() const
        {
           return m_engine;
        }

    private:
       Engine m_engine;
}

简单地将引擎组件公开:

class Car
{
    public:
        Engine engine;
}

如果您不喜欢此示例,也可以将 public 替换为 protected。在现实生活中,当涉及到System.inSystem.out 时,Java 中有类似的东西。看起来,要完全遵守某些人的说法,您需要执行像 System.getInstance().getOut().println("hello world") 这样的调用。在这种情况下,除了大量的官僚代码之外,我没有看到任何好处。

【问题讨论】:

  • 没有近距离投票,但如果问题的目的是陈述一个理论,然后不同意所有与该理论相反的答案,那么它可能是“主观的和有争议的”。你的理论是对是错。
  • @Steve Jessop:别那么热心,按投票排序问题,你会得到很多不准确的问题(问题不能是主观的,答案可以是)。每个答案或多或少都是主观的。原谅你的怀疑 - 我正在旅行,最近没有机会访问 stackoverflow。
  • 这就是我不确定的原因。如果有人真的在为某事寻找理由,我认为这很好,即使可能没有明确的理由。如果有人不相信有任何理由,但无论如何都要问理由,我认为“通常会导致对抗和争论”。两种方式都没有造成严重伤害,但后者不是 AFAIK 网站的目的。

标签: c++ oop getter accessor mutators


【解决方案1】:

当您返回的值实际上在堆上时,它们会很有用。

template<class T> class Singleton
{
private:
    static T* m_pSingleton;

public:
    T& getSingleton() { assert(m_pSingleton); return(*m_pSingleton); };

}; // eo class Singleton

【讨论】:

  • 绝对反对单例模式。
  • 啊,我记得单例模式风靡一时的时代……哎呀,我什至还记得 PEEK 和 POKE 风靡一时的时候。 :-)
  • 是的,数组是邪恶的,getter 和 setter 是邪恶的,单例是邪恶的,整个编程都是邪恶的。最好的程序员是那些没有写过一段代码的人。 +1 因为单例有时很有用。
【解决方案2】:

明确的 getter 和 setter 可能过于官僚;这取决于你的情况。

使用 getter 和 setter 函数的主要原因是它将类的客户端与未来实现中的潜在变化隔离开来(例如,考虑如果您决定按需生成 Engine 对象会发生什么(而不是使用成员变量),或者决定将其隐藏在智能指针或其他容器后面)。

如果您的类非常简单(例如,接近于 POD)并且不太可能更改,那么可能不值得为实现 getter 和 setter 而大费周章。

但是,要回答您的问题,非常量 getter 可能没有多大意义。你的吸气剂原型应该是Engine &amp; engine() const;否则你将无法在 const Car 对象上调用它。

【讨论】:

  • 为了更好地进行谷歌搜索,这称为封装
  • 我已经修复了这个例子。 engine() 方法应该有两个版本:const 和 non-const。在我看来,有时暴露成员和撤回封装很方便。
【解决方案3】:

提供 getter 的一个优点是,当您决定更改 getter 的工作方式时,无需重新编译使用此类的代码。但是如果你有一个公共字段,后来决定做一个吸气剂,所有的代码都应该重新编译。除此之外,我认为没有任何严重的实际理由将您的变量设为私有。但是请注意,当且仅当您必须为外部用户提供一种获取引擎引用的方法时,这一切都成立。如果可以设计软件以完全消除这种需求,那就更好了。

【讨论】:

  • 如果你提供了一个字段,然后再改成getter,客户端代码不仅需要重新编译,还需要重写。
【解决方案4】:

我最近碰巧了解到,getter 和 setter 散发出糟糕设计的味道。但是,如果您希望这样,提供函数来获取和设置m_engine(由您定义)而不是仅仅公开它(您无需干预)意味着您有一个插件点以供将来更改。

【讨论】:

  • 你如何在没有 getter 和 setter 的情况下实现 class Window 的宽度、高度和其他一些属性?我们不会发疯吗?大多数现实生活中的对象都像class Window;几乎简单的结构充满了一些方法。我遇到过采用 SFML 库形式的设计(尽管 Window 有其 GetWidthGetSize 方法),因此我无法很好地扩展它的类。
  • 我的回答有两点。第一个是:封装好。第二个是,如果你不能拥有第一个,那么 getter 和 setter 就很好。第二种情况的想法是,如果您想对Windows 的宽度或高度施加一些约束,则避免将来(或现在)可能发生的代码重复。在第一点上,虽然 setter 可以原谅一点,但为什么需要 getter?这是否意味着您宁愿拥有 getter 暴露在外面的那部分数据?如果是在类里,为什么要让别人篡改(为什么还要提供 const getter)?
  • 在您的问题中,您应该将Mechanic 的对象传递给Car 对象,以便Car 对象可以将其Engine 对象传递给Mechanic 对象.这样,您消除了 getter,Terrorist 将无法访问 Car 的引擎。
  • 检查一下(几周前我问过这个):stackoverflow.com/questions/3933006/… 和这个:idinews.com/quasiClass.pdf。应该转换你:)。
  • @nakiya:封装是关于隐藏实现细节,而不是关于 getter、setter 等等。你可以没有 getter 也没有 setter 并且仍然制动封装!另一方面,如果您不提供类的所有必要部分,那么有人可能无法很好地扩展这个类,这也是错误的。
【解决方案5】:

我找到了合理的理由来提供这样的吸气剂。它使您的软件集成更容易(例如,当您要将界面翻译成另一种语言并绑定 ABI 时)。

【讨论】:

    【解决方案6】:

    对我来说这很有意义:

    image(i,j) = 234;
    

    【讨论】:

      【解决方案7】:

      与其考虑公开类的私有成员,不如多考虑在这些类上调用方法。 我读了一篇有趣的 Java 文章 Why Getter and Setter Methods are Evil,它适用于 C++ 和 Java 一样。

      【讨论】:

      • 是的,我已经阅读并写了标题为“理论只是理论”的评论:) 我的观点是代码由操作和数据组成,而不仅仅是代码。不知何故,你必须修改数据,所以这篇文章显然是错误的。作者没有看到计算背后的大局。他坚持建立在它之上的一些原则,称为面向对象编程。但是没有过程编程就没有 OOP。
      • @doc:如果它没用,为什么要担心理论首先说什么?关于计算机模式,理论不是一些白日梦者想出的抽象数学概念(阅读“Head first design patterns”)。它们是出于需要而诞生的(由于实践中面临的问题)。你的问题就是其中之一。因此,当有人说“Getters and setters are evil”时,并不是说“1 == 1”。
      【解决方案8】:

      是的,这很有意义 - 对于可维护性、验证和一致性而言。

      您将来可能需要更改类的许多方面,提供访问器可以帮助最大限度地减少客户端代码的损坏。

      您可以在此处输入您需要的所有验证逻辑,以确保引擎是有效指针,不处于不可用状态等。

      最后,您的代码将保持一致:您不必打开标题即可知道成员的可见性 - 您总是知道。这对模板也很有用。

      【讨论】:

        【解决方案9】:

        在这种情况下,您宁愿需要一个Car.fix(const Mechanic&amp;) 函数,然后将引擎提供给Mechanic,例如:Engine.fix(const Mechanic&amp;),因为我认为Engine 的状态将被修改。

        使用类的最初想法是将数据与其访问函数联系在一起。如果您使用仅返回内部数据的 setter 或 getter,则意味着您的数据未与其访问器功能绑定在一起:您的类不完整。

        您只想公开类发出的新数据。说Car.get_exhaust()Car 没有排气,只有在您要求时才产生它。 ;)

        或者Fire Riefle.fire(),而Riefle::Trigger 的访问权限将由机制修复,如下所示:Trigger.fix_by(Mechanic),然后fix_by 将调用Mechanic.add_working_hour(0.5)。呵呵

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-19
          • 1970-01-01
          • 2013-06-15
          • 2011-04-12
          • 1970-01-01
          相关资源
          最近更新 更多