C ++为啥在使用类时应该使用get和set函数[重复]

Posted

技术标签:

【中文标题】C ++为啥在使用类时应该使用get和set函数[重复]【英文标题】:C++ Why should I use get and set functions when working with classes [duplicate]C ++为什么在使用类时应该使用get和set函数[重复] 【发布时间】:2013-06-06 17:06:45 【问题描述】:

有人告诉我不要在类中公开我的变量。我应该总是做一个 get 和一个 set 函数。例如:

class Whatever


public:
  void setSentence(const std::string &str)  sentence = str; 
  void setAnInteger(const int integer)  anInteger = integer; 

  std::string getSentence()  return sentence; 
  int getAnInteger()  return anInteger; 

private:
  std::string sentence;
  int anInteger;

;

我为什么要这样做?只是简单地使用这些变量不是更方便吗?另外,这是一种好的 c++ 编程风格吗?

【问题讨论】:

许多人也会反对成员数据本身的getter和setter,支持建模对象的特征的getter和setter (以保持实现的独立性)。 如果您想控制访问/隐藏实现(pimpl,有人吗?),您可以这样做。是的,如果它是内联的,就没有惩罚。你只是不这样做“为了它”。仅当您真的打算更改实现而不更改接口时才这样做。 属性是状态。如果您的对象需要在其属性更改时更新状态(例如,视图对象可能需要在调整大小时重新绘制自身),那么您可能需要能够执行代码。 【参考方案1】:

主要原因是增加封装。如果您的类公开了这些成员变量,则客户端代码中的许多函数将依赖于这些变量。

假设有一天您想更改这些变量的名称,或者您想更改类的实现,以便成员变量的类型和数量与当前不同:有多少函数会受到影响通过这种变化?您需要重写多少个函数(至少部分重写)?

没错,可能是无限的。你不能把它们都数一遍。另一方面,如果你有 getter 和 setter,那么只有这 4 个函数可以访问你的类的内部表示。更改内部表示不需要对客户端函数的代码进行任何更改;只有这 4 个成员函数可能需要更改。

一般来说,封装可以让您的生活更轻松,以应对未来的变化。在某个时间点,您可能希望在每次设置某个属性时记录一条消息。您可能希望在每次设置某个属性时触发一个事件。您可能希望即时计算某个值,而不是每次都从缓存数据成员中读取它,或者从数据库中读取它,或其他任何方式。

拥有 getter 和 setter 允许您实现任何这些更改,而无需更改客户端代码。

【讨论】:

【参考方案2】:

就一般设计理念而言,在实现访问器与不实现访问器时没有“总是”或“从不”,这是整个社区都同意的。

许多人会建议您将所有数据成员设为private 并提供访问器和修改器。总是。

如果不希望从客户端代码更改数据成员,其他人会告诉您创建数据成员 private,否则将其保留为 public

还有一些人会告诉你,类根本不应该有一个或多个数据成员,所有数据都应该封装在另一个对象中,最好是struct

您必须自己决定哪个是正确的,请记住,这不仅取决于您的方法,还取决于您所在组织的方法。

如果你问我,我的偏好是做所有事情public,直到我有理由不这样做。简单的。但这只是我。

【讨论】:

我认为这很合理。特别是对于学习的人来说,知道我现在可以使用 public 是一件好事,如果将来某个时候我看到使用 private 或其他访问修饰符的好处,我可以去使用它们。【参考方案3】:

您编写明确的 getter 和 setter 作为未来发展的明智计划。如果您的类的用户直接访问其成员,并且您需要以与该习惯不兼容的方式更改类,则必须更改以这种方式与您交互的每一块代码。如果您编写 getter 和 setter,编译器会将其优化为与直接访问在时间上等效(如果仅此而已),您可以稍后根据需要更改逻辑 - 而无需更改大量其他代码.

【讨论】:

【参考方案4】:

数据封装是 OOP 的主要原则之一。它是将数据和函数组合成一个称为类的单元的过程。使用封装的方法,程序员不能直接访问数据。数据只能通过类中存在的函数访问,因此类的实现细节对用户是隐藏的。这是为了保护调用者和函数免受意外更改方法的行为,或者需要知道方法如何工作。

【讨论】:

嗯。您能否发布一个示例,说明在直接更改变量时方法如何意外更改行为? 对我的口味来说有点太强硬了。一个人的乌托邦式 OOP 设计指南是另一个人的一堆废话。【参考方案5】:

从我上第一堂 OOP 课时回忆起的教科书式答案是:Get 和 set 方法用于封装私有变量。通常人们会比较 get 和 set 或者只是将这些变量设置为 public;在这种情况下,get 和 set 方法很好,因为它可以保护这些变量不因错误等而被意外修改。

人们(我上那门课时的我)可能会问“不是 get 和 set 也修改这些变量,如果是,那与修改为公共变量有什么不同”。

基本原理是:要拥有 get 和 set 函数,您是在要求用户或您自己明确指定他们要通过调用这些函数来修改变量。如果不调用这些函数,私有变量将不太可能(仍然可能取决于实现)被不情愿或意外地修改。

【讨论】:

【参考方案6】:

当您使用 get 或 set 方法并在代码中使用它 40 次时,您可以更轻松地处理未来的更改。 想象一下,您使用公共变量并在代码中使用它 40 次。在开发程序一个月后,你会想出一个好主意:如果我将这个变量除以 1000 会怎样,这样我就有更好的值来计算! 哇,太好了,但现在我必须找到每一行,在哪里使用并更改它。如果我只有一个 get 方法:(

这就是getter和setter的主要原因,即使它们很简单,最好有它。你会感谢自己一次。

【讨论】:

【参考方案7】:

简而言之,您不应该这样做。

一般来说,我建议阅读 Fowler 的 Refactoring,然后您将了解裸数据会阻碍什么,以及哪种访问方式可以很好地对齐。重要的是,整件事是否适用于您的案例。

正如您所知道的利弊,您可以放心地忽略“应该做/不应该”的内容,例如在这个答案的开头或其他内容。

【讨论】:

以上是关于C ++为啥在使用类时应该使用get和set函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥在C语言中,“scanf”竟然可以作为自定义函数的函数名而不报错??

为啥我们需要复制构造函数以及何时应该在 java 中使用复制构造函数

为啥要在 .c 文件中避免使用 #ifdef?

为啥 set/get_default_resource 使用指针而不是引用?

为啥我应该在javascript中的每个函数后使用分号?

为啥不应该在函数式编程中使用变量赋值