那么公共变量有什么用呢?
我是一个十足的新手,脑子里有很多“?”,而且还有很多 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;
}
};
为什么有人会隐藏该变量并实现访问器和修改器,而除了分配新值之外什么也没做< em>只是收到时(没有范围检查等)或不按原样返回值? 好吧,我听说过一些原因,其中一些在某些情况下是令人信服的,但想象一下以这种方式实现一个巨大的类,其中包含很多不需要任何检查和其他东西的变量! 我这样问你,什么时候使用公共变量?你用这个吗?
I'm a total newbie with tons of ?'s in my mind and a lot to experience with C++ yet! There's been something which I find really confusing and it's the use of public variables, I've seen tons of code like this:
class Foo {
private:
int m_somePrivateVar;
public:
void setThatPrivateVar (int const & new_val) {
m_somePrivateVar = new_val;
}
int getThatPrivateVar (void) const {
return m_somePrivateVar;
}
};
Why would anyone hide that variable and implement accessors and mutators when there's nothing done in them more than assigning the new value just as it got received (no range checking etc.) or returning the value without just as it is?
Well I've heard some reasons and some of them are convincing in some cases, but imagine implementing a huge class in such a manner for with a lot of variables which do not need any checking and stuff!
Let me ask you this way, When do you use public variables? Do you use that at all?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
通过现在隐藏变量并添加方法,类设计者允许将来在这些方法中插入任意代码,而不会破坏直接使用属性的大量代码。
另请注意,提供大量访问器/修改器方法通常表明您的类设计需要另一种可能的改进。类方法应该实现实际逻辑,而不仅仅是提供对每个成员的访问。
我仅以 struct 形式使用公共变量。例如,我可能有一个表示字符串->值映射的数据库表,其中值是复合数据结构。我只需编写一个结构并使用例如
std::map
来表示数据库表。我不需要实际处理数据,只需能够查找数据并在需要时使用它即可。正如几条评论中所指出的,即使是结构体也通常可以从方法的合理使用中受益,例如几个用于保持成员合理初始化的通用构造函数,一个用于重用结构的明确函数等。
By hiding the variable and adding methods now, the class designer allows for inserting arbitrary code into those methods in the future without breaking tons of code that use the attributes directly.
Also note that providing a lot of accessor/mutator methods is generally a sign that your class design needs another look for possible improvement. Class methods should implement actual logic, not just provide access to each member.
I use public variables only in
struct
form. For example, I might have a database table that represents a string->value mapping, where value is a composite data structure. I'd just write a structure and use for examplestd::map<std::string, MyStruct>
to represent the database table. I don't need to actually do work on the data, merely be able to look it up and make use of it when required.As noted in a couple comments, even
struct
s can often benefit from judicial use of methods, for example a couple of common constructors to keep the members sanely initialized, a clear function to reuse the structure, etc.在我看来,设置器/获取器最令人信服的原因是隔离更改。如果您需要添加范围检查,例如,如果您已经有一个 setter,则可以在 setter 中轻松执行此操作,而不会影响客户端代码。如果您还没有 setter,那么所有客户端代码都需要更新以使用 getter/setter,这可能是一场噩梦。
IMO the most compelling reason for setters/getters is isolating change. If you need to add range checking, for example, if you already have a setter, you can easily do that in your setter without impacting client code. If you don't already have a setter, then all client code needs to be updated to use getters/setters which could be a nightmare.
我部分同意有关使用 getter 和 setter 方法以允许将来更改的其他答案,但仍然存在一个基本问题,您正在公开对象的内部数据以供其他对象修改。
最好通过方法要求对象对其保存的数据执行某些操作,而不是将对象视为值的集合。
这是一篇关于为什么 Getter 和 Setter 方法是邪恶的的有趣文章,它是考虑到 Java 编写的,但同样适用于 C++。
I agree, in part, with the other answers regarding the use of getter and setter methods to allow for future changes but there is still a fundamental problem, you are exposing the internal data of your object for other objects to modify.
It is better to ask the object to perform some action on the data it holds, via a method, rather than treat the object as a collection of values.
Here's an interesting article on Why Getter and Setter Methods are Evil, it's written with Java in mind but the same applies to C++.
任何公开的内容都成为该对象契约的一部分。如果您公开公开数据,那么当数据值发生更改时,数据必须继续正常运行。对于结构类型对象,这可能很合适。
拥有大量的 getter 和 setter 可能是一个警告信号,表明该对象实际上是一个结构体,最好直接公开字段。但是,我已经实现了结构类型对象,以便允许字段具有多个名称。根据需要,字段可以有多个 setter 或 getter,从而允许不同域之间的名称转换。真实的字段有描述性名称。其他 getter 和 setter 使用这些字段的域特定代码。
正如其他人所指出的,getter 和 setter 指示字段的存在。不要求这样的字段存在,只要求其行为存在。将 getter 和 setter 公开意味着公众有理由能够修改或读取该字段的值。请三思而后行,您可能会更改方法名称或不将其公开。
Anything exposed as public becomes part of the contract of that object. If you expose data publicly then it must continue to behave properly when the data values are changed. For struct type objects this may well be appropriate.
Having a high number of getters and setters can be a warning sign that the object is really a struct and it may be better to expose the fields directly. However, I have implemented struct type objects in order to allow fields to have multiple names. Fields could have multiple setters or getters as required allowing name translation between different domains. The real fields had descriptive names. Additional getters and setters used the domain specific codes for those fields.
As other have noted, getters and setters are indicative of the presence of a field. There is no requirement that such a field exist, only that its behavior exists. Making the getters and setters public implies there is a reason for the public to be able to modify or read the value of that field. Think twice about the purpose, and you may change the method name or not make it public.
一个论点是这样的:
如果相关类的外部代码直接依赖于某个特定成员,则对该成员进行更改意味着更改访问该成员的每一段代码。如果相反,它是由成员函数访问的,则可以保持接口的该部分相同,并且只需对该类进行更改即可保持外部代码正常工作。
使用“getters”和“setters”为您的对象耦合提供了一定的灵活性。
One argument runs something like this:
If code external to the class in question relies directly on a particular member, making a change to that member means changing every piece of code that accesses it. If instead it is accessed by member functions, you can keep that part of the interface the same, and only have to make changes to that class to keep external code working.
Using "getters" and "setters" gives you some flexibility built into the coupling of your objects.
这些被称为“getter”和“setter”。使用它们的一个很好的理由是您可以稍后添加额外的代码而无需更改界面。在您的示例中,它们看起来作用不大,但在更复杂的类中,它们实际上是必不可少的。
These are called "getters" and "setters." One good reason to use them is that you can add extra code later without changing the interface. In your example it doesn't look like they do much, but in more complex classes they're practically essential.
好的,据我了解,您的问题是这样的:为什么将变量设为私有,然后创建两个仅检索值并设置值而不进行任何检查的函数?如果有支票,你就会明白,不是吗?例如,如果您设置 Time 类的 hour 字段,则检查
hour <= 24
是个好主意。但是,当不应用检查时,想法是这样的:如果在某个时候您决定更改设置和获取函数,例如,在其中执行一些检查,则不需要重新编译使用您的类的整个代码
另外,封装的一般目的是仅通过类的接口与类进行通信,而不知道它是如何实现的。你隐藏的内部信息越多越好。
什么时候使用公共变量?当你制作没有行为的对象时。那些只是数据的集合体。例如,请参阅
std::pair
。一对只是一个结构体,具有公共first
和second
。一般来说,什么时候使用哪种方式,我们无法给出一个严格的标准,但随着经验的积累,你会自己感受到。
高温
OK, As I understand, your question is this: Why make a variable private and then make two functions which just retrieve the value and set the value without any checks? If there were checks, you'd understand, wouldn't you? For example, if you set the hour field of a Time class, checking that
hour <= 24
is a good idea.But when no checks are applied the idea is this: if at some point you decide to change the setting and getting functions, for example, perform some checks in them, the whole code that has been using your class need not be recompiled
Also, the general purpose of encapsulation is that one communicate with the class only via its interface, without knowing how it is implemented. The more inner info you hide, the better.
When do you use public variables? When you make objects that have no behavior. Ones that are just a conglomerate of data. For example, see
std::pair
. A pair is just a struct, with publicfirst
andsecond
.In general, one cannot give a strict criteria when to use which way, but you'll feel it yourself with gain of experience.
HTh
正如 Scott Meyers 在《Effective C++》一书中所说:避免在公共接口中使用数据成员。
为什么?因为它更容易编码(一切都是成员函数),而且您可以更好地控制该变量的访问,以及 Doug T. 和其他人关于函数抽象的说法。
如果您不需要类(如您的示例中所示),您可以选择使用结构...
查看 这篇文章由斯科特写,如果你没有这本书:)
As Scott Meyers says on Effective C++ book: Avoid data members in the public interface.
Why? because it's more easy to code (everything is a member function), also you have more control on the access of that variable, and what Doug T. and the others said about functional abstraction.
If you don't need a class (like in your example) you have the choice of use a struct...
Look this post written by Scott if you don't have the book :)
我不能同意公众是邪恶的这种观点。 C++ 不是 C#。在用 C++ 编码时,我总是会避免一些我并不真正需要的东西。 那么使用公共成员是完全可以的
不管有些人怎么说,我相信与使用某些函数调用来执行几乎相同的操作相比,访问公共变量会产生更干净的代码。这当然取决于它是什么类型的项目以及该类将如何使用以及将来可能如何使用。在我看来,编写 getter 和 setter 以防万一是没有用的。
作为参考,请阅读 C++指南(C.131)
I cannot agree with this opinion that public members are evil. C++ is not C#. I would always avoid things that I don't really need when coding in C++. Using public members is completely fine if
Despite what some people say, I believe accessing public variable leads to a cleaner code than using some function calls to do practically the same. This of course depends on what kind of project it is and how will the class be used and how it might be used in the future. Writing getters and setter just in case is in my humble opinion useless.
As a reference, read C++ guidelines (C.131)
这只是一个基本的练习。您设计一个类的公共接口,调用者可以安全地访问该类。如果它们只是方法,那么它们的内容可以稍后更改。如果他们是公共数据成员,您将永远与他们在一起。您无法更改公共变量的作用。
某些编程语言(OOP 模型)使用属性来实现相同的想法。如果您的公共接口仅由代码组成,您可以随时更改内部工作方式,保持接口(以及使用它的其他代码)完好无损。如果你的公共接口包含数据,你就会限制你未来的开发可能性。
It is just a basic practice. You design the public interface of a class which can be safely accessed by the callers. If they are just methods, their content can be changed later. If they are public data members you are stck with them forever. You can not change what a public variable does.
Some programming languages (OOP models) use properties for the same idea. If your public interface only consists of code, you can change the inner workings at any time leaving the interface (and other code which is using it) intact. If your public interface contains data, you restrict your future development possibilies.
我知道在Java中我们使用公共变量,事实上,
变量作为在引入枚举之前指定常量的手段。
例如,
我研究 C++ 已经有一段时间了,所以不确定是否有可用的枚举类型。如果枚举在 C++ 中不可用,您可以使用上面类似的代码
I know in Java we use public variables, in fact,
variables as means to specify constants before enumeration was introduced.
For example,
It has been a while I looked into C++, so not sure if there are enumerated types available. You can use the similar code above if enumeration is not available in C++
在大多数情况下,getter 和 setter 确实是一个很好的实践。但事实是,您当前的示例太简单,因此不是一个很好的候选者通过 get/set() 来保护私有成员访问。
Getters and setters are indeed a good practice in most cases. But the fact is that your current example is too simple, and therefore is not a good candidate for defending private members access through get/set().
更有趣的趋势之一是自动实现的属性。因此,您不必编写 getter 和 setter,只需编写一个属性,编译器就会完成剩下的工作。您仍然可以选择编写 getter 和 setter,但不必为应该只有 1 行的内容编写所有样板代码。如果您稍后需要添加范围检查等,您只需以老式方式创建属性并保持类的接口相同即可。
我在最新版本的 C#、Objective-C 和 VB 中看到过这一点,它非常有帮助。 VB 的实现没有提供与 C# 一样多的灵活性,但我相信它会很快赶上。
One of the more interesting trends is auto implemented properties. So instead of having to write the getters and setters you just have to write a property and the compiler does the rest. You still have the option of writing the getters and setters, but you don't have to write all of the boiler plate code for what should just be 1 line. If you need to add range checking etc later, you can just create the property the old fashioned way and keep the interface to your class the same.
I have seen this in the latest versions of C#, Objective-C and VB and it can be quite helpful. VB's implementation doesn't offer as much flexibility as C#, but I am sure it will catch up pretty quickly.
我不太关心编写什么都不做的访问器。我持这种态度有两个原因。
这样做的原因之一是代码稍后会继承自。我发现这在实践中通常是不正确的。通常发生的情况是代码被重构或替换。代码的生命周期几乎总是很短。
您现在正在为将来可能发生或可能不会发生的事情做额外的工作。这是“过早优化”错误的变体。
有些地方这是个好主意,有些地方则不然。在大多数情况下,我觉得答案是它没有用。
I don't care much for writing accessors that do nothing. I have two reasons for this attitude.
One of the reasons for doing so is that the code will later be inherited from. I've found this is usually not true in practice. What usually happens is the code is refactored or replaced. The lifespan of code is almost always very short.
You're making extra work now for something that might, or might not, happen in the future. This is a variation of the "premature optimization" fault.
There are places where it's a good idea and places where it's not. In most cases I feel the answer is it's not useful.