C++ 我应该使用公共变量还是私有变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14399929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:18:58  来源:igfitidea点击:

Should I use public or private variables?

c++oopabstractiongetter-setterdata-access

提问by Marek ?a?ko

I am doing a large project for the first time. I have lots of classes and some of them have public variables, some have private variables with setter and getter methods and same have both types.

我是第一次做一个大项目。我有很多类,其中一些有公共变量,一些有带有 setter 和 getter 方法的私有变量,同样有两种类型。

I decided to rewrite this code to use primarily only one type. But I don't know which I should use (variables which are used only for methods in the same object are always private and are not subject of this question).

我决定重写这段代码,主要只使用一种类型。但我不知道我应该使用哪个(仅用于同一对象中的方法的变量始终是私有的,而不是这个问题的主题)。

I know the theory what public and private means, but what is used in the real world and why?

我知道公共和私人意味着什么的理论,但在现实世界中使用的是什么,为什么?

回答by Luchian Grigore

privatedata members are generally considered good because they provide encapsulation.

private数据成员通常被认为是好的,因为它们提供封装。

Providing getters and setters for them breaks that encapsulation, but it's still better than publicdata members because there's only once access point to that data.

为它们提供 getter 和 setter 会破坏这种封装,但它仍然比public数据成员好,因为只有一次访问该数据的访问点。

You'll notice this during debugging. If it's private, you knowyou can only modify the variable inside the class. If it's public, you'll have to search the whole code-base for where it mightbe modified.

您会在调试期间注意到这一点。如果它是私有的,你知道你只能修改类中的变量。如果它是公开的,则必须搜索整个代码库以查找可能被修改的位置。

As much as possible, ban getters/setters and make properties private. This follows the principle of information hiding - you shouldn't care about what properties a class has. It should be self-contained. Of course, in practice this isn't feasible, and if it is, a design that follows this will be more cluttered and harder to maintain than one that doesn't.

尽可能禁止 getter/setter 和 make properties private。这遵循信息隐藏的原则——你不应该关心一个类有什么属性。它应该是独立的。当然,在实践中这是不可行的,如果可行,那么遵循此规则的设计将比不遵循此规则的设计更加混乱且难以维护。

This is of course a rule of thumb - for example, I'd just use a struct(equivalent with a classwith public access) for, say, a simple point class:

这当然是一个经验法则——例如,我只是将 a struct(相当于class具有公共访问权限的 a)用于一个简单的点类:

struct Point2D
{
   double x;
   double y;
};

回答by Baltasarq

Since you say that you know the theory, and other answers have dug into the meaning of public/private, getters and setters, I'd like to focus myself on the why of using accessors instead of creating public attributes (member data in C++).

既然你说你知道这个理论,而其他答案已经深入研究了 public/private、getter 和 setter 的含义,我想把自己的注意力集中在为什么使用访问器而不是创建公共属性(C++ 中的成员数据)上.

Imagine that you have a class Truck in a logistic project:

想象一下,你在一个物流项目中有一个卡车类:

class Truck {
public:
    double capacity;

    // lots of more things...
};

Provided you are northamerican, you'll probably use gallons in order to represent the capacity of your trucks. Imagine that your project is finished, it works perfectly, though many direct uses of Truck::capacityare done. Actually, your project becomes a success, so some european firm asks you to adapt your project to them; unfortunately, the project should use the metric system now, so litres instead of gallons should be employed for capacity.

如果您是北美人,您可能会使用加仑来表示卡车的容量。想象一下,您的项目已经完成,它运行良好,尽管Truck::capacity已经完成了许多直接使用。实际上,您的项目取得了成功,因此一些欧洲公司要求您根据他们的情况调整您的项目;不幸的是,该项目现在应该使用公制系统,因此容量应使用升而不是加仑。

Now, this could be a mess. Of course, one possibility would be to prepare a codebase only for North America, and a codebase only for Europe. But this means that bug fixes should be applied in two different code sources, and that is decided to be unfeasible.

现在,这可能是一团糟。当然,一种可能性是只为北美准备一个代码库,只为欧洲准备一个代码库。但这意味着应该在两个不同的代码源中应用错误修复,这被认为是不可行的。

The solution is to create a configuration possibility in your project. The user should be able to set gallons or litres, instead of that being a fixed, hardwired choice of gallons.

解决方案是在您的项目中创建配置可能性。用户应该能够设置加仑或升,而不是固定的、硬连线的加仑选择。

With the approach seen above, this will mean a lot of work, you will have to track down all uses of Truck::capacity, and decide what to do with them. This will probably mean to modify files along the whole codebase. Let's suppose, as an alternative, that you decided a more theoreticapproach.

使用上面看到的方法,这将意味着大量的工作,您必须追踪 的所有用途Truck::capacity,并决定如何处理它们。这可能意味着修改整个代码库中的文件。作为替代方案,让我们假设您决定采用更多theoretic方法。

class Truck {
public:
    double getCapacity() const
        { return capacity; }

    // lots of more things...
private:
    double capacity;
};

A possible, alternative change involves no modification to the interface of the class:

一个可能的替代更改不涉及对类的接口的修改:

class Truck {
public:
    double getCapacity() const
        { if ( Configuration::Measure == Gallons ) {
            return capacity;
          } else {
             return ( capacity * 3.78 );
          }
        }


    // lots of more things...
private:
    double capacity;
};

(Please take int account that there are lots of ways for doing this, that one is only one possibility, and this is only an example)

(请注意,有很多方法可以做到这一点,只有一种可能性,这只是一个例子)

You'll have to create the global utility class configuration (but you had to do it anyway), and add an include in truck.hfor configuration.h, but these are all local changes, the remaining of your codebase stays unchanged, thus avoiding potential bugs.

您必须创建全局实用程序类配置(但无论如何您必须这样做),并在truck.hfor 中添加一个包含configuration.h,但这些都是本地更改,您的代码库的其余部分保持不变,从而避免潜在的错误。

Finally, you also state that you are working now in a big project, which I think it is the kind of field in which these reasons actually make more sense. Remember that the objective to keep in mind while working in large projects is to create maintainable code, i.e., code that you can correct and extend with new functionalities. You can forget about getters and setters in personal, small projects, though I'd try to make myself used to them.

最后,你还说你现在正在从事一个大项目,我认为在这个领域,这些原因实际上更有意义。请记住,在大型项目中工作时要记住的目标是创建可维护的代码,即您可以使用新功能更正和扩展的代码。您可以忘记个人小项目中的 getter 和 setter,尽管我会尽量让自己习惯它们。

Hope this helps.

希望这可以帮助。

回答by HAL

There is no hard rule as to what should be private/public or protected.

关于什么应该是私有/公共或受保护的,没有硬性规定。

It depends on the role of your class and what it offers.

这取决于您班级的角色及其提供的内容。

  • All the methods and members that constitute the internal workings of the class should be made private.
  • Everything that a class offers to the outside world should be public.
  • Members and methods that may have to be extended in a specialization of this class, could be declared as protected.
  • 构成类内部工作的所有方法和成员都应设为私有
  • 一个类提供给外部世界的一切都应该是公开的
  • 可能必须在此类的特化中扩展的成员和方法可以声明为protected

回答by sth

From an OOP point of view getters/setters help with encapsulation and should therefore always be used. When you call a getter/setter the class can do whatever it wants behind the scenes and the internals of the class are not exposed to the outside.

从 OOP 的角度来看,getter/setter 有助于封装,因此应始终使用。当您调用 getter/setter 时,类可以在幕后做任何它想做的事情,并且类的内部结构不会暴露给外部。

On the other hand, from a C++ point of view, it can also be a disadvantage if the class does lots of unexpected things when you just want to get/set a value. People like to know if some access results in huge overhead or is simple and efficient. When you access a public variable you know exactly what you get, when you use a getter/setter you have no idea.

另一方面,从 C++ 的角度来看,如果当您只想获取/设置一个值时,类做了很多意想不到的事情,这也可能是一个缺点。人们想知道某些访问是否会导致巨大的开销,或者是否简单有效。当你访问一个公共变量时,你确切地知道你得到了什么,当你使用 getter/setter 时,你不知道。

Especially if you only do a small project, spending your time writing getters/setters and adjusting them all accordingly when you decide to change your variable name/type/... produces lots of busywork for little gain. You'd better spend that time writing code that does something useful.

特别是如果你只做一个小项目,花时间编写 getter/setter 并在你决定更改变量名称/类型/...时相应地调整它们。你最好花时间写一些有用的代码。

C++ code commonly doesn't use getters/setters when they don't provide real gain. If you design a 1,000,000-line project with lots of modules that have to be as independent as possible it might make sense, but for most normal-sized code you write day to day they are overkill.

C++ 代码在不提供实际收益时通常不使用 getter/setter。如果您设计一个 1,000,000 行的项目,其中包含许多必须尽可能独立的模块,这可能是有道理的,但对于您每天编写的大多数正常大小的代码来说,它们是矫枉过正的。

回答by Pete Becker

There are some data types whose sole purpose is to hold well-specified data. These can typically be written as structs with public data members. Aside from that, a class should define an abstraction. Public variables or trivial setters and getters suggest that the design hasn't been thought through sufficiently, resulting in an agglomeration of weak abstractions that don't abstract much of anything. Instead of thinking about data, think about behavior: this class should do X, Y, and Z. From there, decide what internal data is needed to support the desired behavior. That's not easy at first, but keep reminding yourself that it's behavior that matters, not data.

有一些数据类型的唯一目的是保存明确指定的数据。这些通常可以写为具有公共数据成员的结构。除此之外,一个类应该定义一个抽象。公共变量或微不足道的 setter 和 getter 表明设计没有经过充分的考虑,导致弱抽象的聚集,没有抽象任何东西。与其考虑数据,不如考虑行为:这个类应该做 X、Y 和 Z。从那里决定需要哪些内部数据来支持所需的行为。一开始这并不容易,但要不断提醒自己,重要的是行为,而不是数据。

回答by codemaster91

Private member variables are preferred over public member variables, mainly for the reasons stated above (encapsulation, well-specified data, etc..). They also provide some data protection as well, since it guarantees that no outside entity can alter the member variable without going through the proper channel of a setter if need be.

私有成员变量优于公共成员变量,主要是出于上述原因(封装、明确指定的数据等)。它们还提供了一些数据保护,因为它保证在需要时没有外部实体可以在不通过 setter 的适当通道的情况下更改成员变量。

Another benefit of getters and setters is that if you are using an IDE (like Eclipse or Netbeans), you can use the IDE's functionality to search for everyplace in the codebase where the function is called. They provide visibility as to where a piece of data in that particular class is being used or modified. Also, you can easily make the access to the member variables thread safe by having an internal mutex. The getter/setter functions would grab this mutex before accessing or modifying the variable.

getter 和 setter 的另一个好处是,如果您使用的是 IDE(如 Eclipse 或 Netbeans),则可以使用 IDE 的功能来搜索代码库中调用该函数的每个位置。它们提供了有关该特定类中的数据被使用或修改的位置的可见性。此外,您可以通过内部互斥锁轻松地访问成员变量线程安全。getter/setter 函数会在访问或修改变量之前获取这个互斥锁。

I'm a proponent of abstraction to the point where it is still useful. Abstraction for the sake of abstraction usually results in a cluttered mess that is more complicated than its worth.

我是抽象的支持者,它仍然有用。为了抽象而抽象通常会导致比其价值更复杂的混乱。

回答by Stefan Seidel

Public variables are usually discouraged, and the better form is to make all variables private and access them with getters and setters:

通常不鼓励使用公共变量,更好的形式是将所有变量设为私有并使用 getter 和 setter 访问它们:

private int var;

public int getVar() {
  return var;
}

public void setVar(int _var) {
  var = _var;
}

Modern IDEs like Eclipse and others help you doing this by providing features like "Implement Getters and Setters" and "Encapsulate Field" (which replaces all direct acccesses of variables with the corresponding getter and setter calls).

Eclipse 等现代 IDE 可通过提供“实现 Getter 和 Setter”和“封装字段”等功能(用相应的 getter 和 setter 调用替换所有变量的直接访问)来帮助您做到这一点。