具有成员函数的 C++ 结构与具有公共变量的类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15572665/
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
C++ Structs with Member Functions vs. Classes with Public Variables
提问by amnesia
This is really a question of good form/best practices. I use structs in C++ to form objects that are designed to basically hold data, rather than making a class with a ton of accessor methods that do nothing but get/set the values. For example:
这确实是一个良好形式/最佳实践的问题。我使用 C++ 中的结构来形成旨在基本上保存数据的对象,而不是使用大量访问器方法创建一个类,这些方法除了获取/设置值之外什么都不做。例如:
struct Person {
std::string name;
DateObject dob;
(...)
};
If you imagine 20 more variables there, writing this as a class with private members and 40-something accessors is a pain to manage and seems wasteful to me.
如果你想象那里有 20 个以上的变量,把它写成一个带有私有成员和 40 多个访问器的类是一种管理起来很痛苦的事情,对我来说似乎很浪费。
Sometimes though, I might need to also add some sort of minimal functionality to the data. In the example, say I also sometimes need the age, based on dob:
但有时,我可能还需要向数据添加某种最小功能。在示例中,假设我有时也需要年龄,基于 dob:
struct Person {
std::string name;
DateObject dob;
(...)
int age() {return calculated age from dob;}
}
Of course for any complex functionality I would make a class, but for just a simple functionality like this, is this "bad design"? If I do use a class, is it bad form to keep the data variables as public class members, or do I just need to accept it and make classes with a bunch of accessor methods? I understand the differences between classes and structs, I'm just asking about best practices.
当然,对于任何复杂的功能,我都会创建一个类,但是对于像这样的简单功能,这是“糟糕的设计”吗?如果我确实使用了一个类,将数据变量保留为公共类成员是不是很糟糕,还是我只需要接受它并使用一堆访问器方法创建类?我了解类和结构之间的区别,我只是在询问最佳实践。
采纳答案by Joseph Mansfield
I think there are two important design principles to consider here:
我认为这里有两个重要的设计原则需要考虑:
Hide a class's representation through an interface if there is some invariant on that class.
A class has an invariant when there is such thing as an invalid state for that class. The class should maintain its invariant at all times.
Consider a
Point
type that represents a 2D geometric point. This should just be astruct
with publicx
andy
data members. There is no such thing as an invalid point. Every combination ofx
andy
values is perfectly fine.In the case of a
Person
, whether it has invariants depends entirely on the problem at hand. Do you consider such things as an empty name as a valid name? Can thePerson
have any date of birth? For your case, I think the answer is yes and your class should keep the members public.Non-friend non-member functions improve encapsulation.
There's no reason your
age
function should be implemented as a member function. The result ofage
can be calculated using the public interface ofPerson
, so it has no reason to be a member function. Place it in the same namespace asPerson
so that it is found by argument-dependent lookup. Functions found by ADL are part of the interface of that class; they just don't have access to private data.If you did make it a member function and one day introduced some private state to
Person
, you would have an unnecessary dependency. Suddenlyage
has more access to data than it needs.
如果该类有一些不变量,则通过接口隐藏该类的表示。
当该类存在无效状态时,该类具有不变量。该类应始终保持其不变性。
考虑一种
Point
表示 2D 几何点的类型。这应该只是一个struct
公共x
和y
数据成员。没有无效点这样的东西。x
和y
值的每个组合都非常好。在 a 的情况下
Person
,它是否有不变量完全取决于手头的问题。您认为空名称之类的东西是有效名称吗?可以Person
有任何出生日期吗?对于你的情况,我认为答案是肯定的,你的班级应该让成员公开。请参阅:类应该强制执行不变量
非友非成员函数提高了封装性。
没有理由将您的
age
函数实现为成员函数。的结果age
可以使用 的公共接口计算Person
,所以没有理由成为成员函数。将它放在与Person
参数相关的查找相同的命名空间中。ADL 找到的函数是该类接口的一部分;他们只是无权访问私人数据。如果您确实将其设为成员函数,并且有一天向 引入了一些私有状态
Person
,那么您将拥有不必要的依赖项。突然间,age
对数据的访问超出了它的需要。请参阅:非成员函数如何改进封装
So here's how I would implement it:
所以这是我将如何实现它:
struct Person {
std::string name;
DateObject dob;
};
int age(const Person& person) {
return calculated age from person.dob;
}
回答by Polar
In C++, Structs are classes, with the onlydifference (that I can think of, at least) being that in Structs members are public by default, but in classes they are private. This means it is perfectly acceptable to use Structs as you are - this articleexplains it well.
在 C++ 中,Structs 是类,唯一的区别(至少我能想到)是 Structs 中的成员默认是公共的,但在类中它们是私有的。这意味着按原样使用 Structs 是完全可以接受的 -这篇文章很好地解释了它。
回答by Mohammed Hossain
In C++, the only difference between structs and classes are that structs are publicly visibly by default. A good guideline is to use structs as plain-old-data (POD) that only hold data and use classes for when more functionality (member functions) is required.
在 C++ 中,结构体和类之间的唯一区别是结构体默认是公开可见的。一个好的指导方针是将结构用作只保存数据的普通旧数据 (POD),并在需要更多功能(成员函数)时使用类。
You may still be wondering whether to just have public variables in the class or use member functions; consider the following scenario.
您可能仍然想知道是在类中只使用公共变量还是使用成员函数;考虑以下场景。
Let's say you have a class A
that has a function GetSomeVariable
that is merely a getter for a private variable:
假设你有一个类A
,它有一个函数GetSomeVariable
,它只是一个私有变量的 getter:
class A
{
double _someVariable;
public:
double GetSomeVariable() { return _someVariable; }
};
What if, twenty years down the line, the meaning of that variable changes, and you have to, let's say, multiply it by 0.5? When using a getter, it is simple; just return the variable multiplied by 0.5:
如果 20 年后,该变量的含义发生变化,并且您必须将其乘以 0.5,该怎么办?使用 getter 时,很简单;只需返回乘以 0.5 的变量:
double GetSomeVariable() { return 0.5*_someVariable; }
By doing this, you allow for easy maintainability and allow for easy modification.
通过这样做,您可以轻松维护并允许轻松修改。
回答by Arun
If you want some data holder then prefer struct without any get/set methods.
如果你想要一些数据持有者,那么更喜欢没有任何 get/set 方法的结构。
If there is more to it, as in this case "Person".
如果还有更多内容,如本例中的“人”。
- It models real world entity,
- Has definite state and behaviour,
- Interacts with external world,
- Exhibits simple/complex relationship with other entities,
- it may evolve overtime,
- 它模拟现实世界的实体,
- 有明确的状态和行为,
- 与外部世界互动,
- 与其他实体表现出简单/复杂的关系,
- 它可能会随着时间的推移而演变,
then it is a perfect candidate for a class.
那么它是一个班级的完美候选人。
回答by SomeWittyUsername
I don't want to sparkle a holy war here; I usually differentiate it in this way:
我不想在这里引发一场圣战;我通常是这样区分的:
- For POD objects (i.e., data-only, without exposed behavior) declare the internals public and access them directly. Usage of
struct
keyword is convenient here and also serves as a hint of the object usage. - For non-POD objects declare the internals private and define public getters/setters. Usage of
class
keyword is more natural in these cases.
- 对于 POD 对象(即,仅数据,没有暴露的行为)声明内部公共并直接访问它们。的使用
struct
关键字是方便在这里,也作为对象使用的提示。 - 对于非 POD 对象,声明内部私有并定义公共 getter/setter。
class
在这些情况下,关键字的使用更自然。
回答by citykid
"Use a struct only for passive objects that carry data; everything else is a class."
“仅对携带数据的被动对象使用结构;其他一切都是一个类。”
say google guidlines, I do it this way and find it a good rule. Beside that I think you can define your own pragmatics, or deviate from this rule if it really makes sense.
说谷歌指南,我这样做并发现它是一个很好的规则。除此之外,我认为您可以定义自己的语用学,或者如果确实有意义,则可以偏离此规则。