那么公共变量有什么用呢?

时间:2011-03-02 14:35:42

标签: c++ oop encapsulation

我是一个全新的,有很多?在我的脑海中,还有很多用C ++体验过的东西!有些东西我觉得很混乱,而且是公共变量的使用,我见过很多这样的代码:

class Foo {

private:
    int m_somePrivateVar;

public:
    void setThatPrivateVar (int const & new_val) {
        m_somePrivateVar = new_val;
    }

    int getThatPrivateVar (void) const {
        return m_somePrivateVar;
    }

};

为什么有人会隐藏该变量并实现访问器和更改器,当它们没有完成任何操作时,只需分配新值只是,因为它已收到(没有范围检查等)或返回值没有就像它一样? 好吧,我已经听到了一些原因,其中一些在一些案例中有说服力,但想象一下如此实现一个庞大的类,有很多变量,不需要任何检查和东西! 我这样问你,你什么时候使用公共变量?你根本使用它吗?

14 个答案:

答案 0 :(得分:41)

通过隐藏变量并立即添加方法,类设计器允许将来将任意代码插入到这些方法中,而不会破坏大量直接使用这些属性的代码。

另请注意,提供大量的accessor / mutator方法通常表明您的类设计需要另外寻找可能的改进。类方法应该实现实际逻辑,而不仅仅是提供对每个成员的访问。

我仅以struct形式使用公共变量。例如,我可能有一个表示字符串 - &gt;值映射的数据库表,其中value是复合数据结构。我只是编写一个结构并使用例如std::map<std::string, MyStruct>来表示数据库表。我不需要实际处理数据,只需要查找并在需要时使用它。

正如一些评论中所指出的,即使struct通常也可以从司法使用方法中受益,例如,一些常见的构造函数可以保持成员的理智初始化,重用结构的明确功能等。

答案 1 :(得分:23)

IMO最引人注目的原因是隔离变化。如果您需要添加范围检查,例如,如果您已经有一个setter,则可以在setter中轻松完成,而不会影响客户端代码。如果您还没有setter,那么需要更新所有客户端代码以使用getter / setter,这可能是一场噩梦。

答案 2 :(得分:17)

我同意其他关于使用getter和setter方法的答案以允许将来的更改,但仍然存在一个基本问题,即暴露对象的内部数据以供其他对象修改。< / p>

最好要求对象通过方法对其拥有的数据执行某些操作,而不是将对象视为值的集合。

这是一篇关于Why Getter and Setter Methods are Evil的有趣文章,它是用Java编写的,但同样适用于C ++。

答案 3 :(得分:4)

一个论点运行如下:

如果相关类外部的代码直接依赖于特定成员,则对该成员进行更改意味着更改访问它的每一段代码。相反,如果成员函数访问它,您可以保持接口的那一部分相同,只需要对该类进行更改以保持外部代码的正常工作。

使用“getters”和“setter”可以为对象的耦合提供一些灵活性。

答案 4 :(得分:4)

任何公开的内容都会成为该对象合同的一部分。如果公开公开数据,则在更改数据值时必须继续正常运行。对于结构类型对象,这可能是合适的。

拥有大量的getter和setter可能是一个警告信号,表明该对象实际上是一个struct,最好直接公开这些字段。但是,我已经实现了struct类型对象,以允许字段具有多个名称。字段可以根据需要具有多个setter或getter,允许在不同域之间进行名称转换。真实的字段有描述性的名称。其他getter和setter使用这些字段的域特定代码。

正如其他人所指出的,吸气剂和制定者表明存在一个场。不要求存在这样的字段,只要存在其行为。使getter和setter公开意味着公众有理由能够修改或读取该字段的值。三思而后行,您可以更改方法名称或不公开。

答案 5 :(得分:3)

这些被称为“getters”和“setters”。使用它们的一个很好的理由是,您可以在以后添加额外的代码而无需更改界面。在你的例子中,它看起来并不多,但在更复杂的类中,它们实际上是必不可少的。

答案 6 :(得分:3)

好的,据我所知,你的问题是这样的:为什么要将变量设为私有,然后创建两个函数,只检索值并设置值而不进行任何检查?如果有支票,你会明白,不是吗?例如,如果您设置时间类的小时字段,请检查hour <= 24是个好主意。

但是当没有应用任何检查时,这个想法就是这样:如果在某些时候你决定更改设置并获取功能,例如,在其中执行一些检查,那么使用你的类需要的整个代码不能重新编译

此外,封装的一般目的是只通过其接口与类进行通信,而不知道它是如何实现的。隐藏的内部信息越多越好。

什么时候使用公共变量?当您创建没有行为的对象时。那些只是数据集团的人。例如,请参阅std::pair。一对只是一个结构,公共firstsecond

一般情况下,人们在使用哪种方式时不能给出严格的标准,但是你可以通过经验获得自己的感受。

HTH

答案 7 :(得分:3)

正如Scott Meyers在Effective C ++上所说:避免公共接口中的数据成员。 为什么?因为它更容易编码(一切都是成员函数),你也可以更好地控制该变量的访问,以及Doug T.和其他人对功能抽象的看法。

如果您不需要课程(如您的示例),您可以选择使用结构...

如果您没有这本书,请查看Scott撰写的this post:)

答案 8 :(得分:1)

我不同意公众成员邪恶的观点。 C ++不是C#。在C ++编码时,我总是会避免使用我真正不需要的东西。如果

,使用公共成员就完全没问题了
  • 您的公共变量不能设置为undefined,out of bounds或某种方式已损坏的值
  • 你知道没有人会试图破坏你的对象(意味着使用它的模块知道完全如何处理它)
  • 您不需要由get / set action
  • 引起的任何其他额外检查或对象修改
  • 你100%确定你将来不需要任何提到的东西

尽管有些人说,我相信访问公共变量会导致代码比使用某些函数调用更简洁。这当然取决于它是什么类型的项目以及如何使用该类以及将来如何使用它。编写getter和setter 以防万一在我的拙见中毫无用处。

As a reference, read C++ guidelines (C.131)

答案 9 :(得分:0)

这只是一个基本的练习。您可以设计一个可以由调用者安全访问的类的公共接口。如果它们只是方法,则可以在以后更改其内容。如果他们是公共数据成员,那么您将永远与他们交往。你无法改变公共变量的作用。

某些编程语言(OOP模型)使用属性来实现相同的想法。如果您的公共接口仅由代码组成,则可以随时更改内部工作,使接口(以及正在使用它的其他代码)保持不变。如果您的公共界面包含数据,则会限制您未来的开发可能性。

答案 10 :(得分:0)

我知道在Java中我们使用公共变量,事实上,

  

public static final

变量作为在枚举之前指定常量的方法。

例如,

class Direction
{

public static final String NORTH = "north";
...
}

我一直在研究C ++,所以不确定是否有可用的枚举类型。如果枚举在C ++中不可用,则可以使用上面的类似代码

答案 11 :(得分:0)

在大多数情况下,吸气剂和制定者确实是一种很好的做法。但事实是你当前的例子过于简单,因此不是一个好的候选人,可以通过get / set()来保护私人成员的访问权。

答案 12 :(得分:0)

一个更有趣的趋势是自动实现的属性。因此,您不必编写getter和setter,而只需编写一个属性,然后编译器完成剩下的工作。您仍然可以选择编写getter和setter,但是您不必编写所有的锅炉板代码,只需要1行。如果您以后需要添加范围检查等,您可以以旧式方式创建属性,并保持与您的类的接口相同。

我在最新版本的C#,Objective-C和VB中看到了这一点,它可能非常有用。 VB的实现并没有提供与C#一样多的灵活性,但我相信它会很快赶上来。

答案 13 :(得分:0)

我并不关心编写什么都不做的访问器。这种态度有两个原因。

  • 这样做的原因之一是以后会继承代码。我发现这在实践中通常不正确。通常发生的是代码被重构或替换。代码的生命周期几乎总是很短。

  • 你现在正在为可能会或将来可能不会发生的事情做额外的工作。这是“premature optimization”错误的变体。

有些地方有一个好主意,有些地方不是。在大多数情况下,我觉得答案是没用的。