具有成员函数的 C++ 结构与具有公共变量的类
这确实是一个关于良好形式/最佳实践的问题.我在 C++ 中使用结构来形成旨在基本上保存数据的对象,而不是使用大量访问器方法创建一个类,这些访问器方法除了获取/设置值之外什么都不做.例如:
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:
struct Person {
std::string name;
DateObject dob;
(...)
};
如果你想象那里有 20 个以上的变量,把它写成一个包含私有成员和 40 多个访问器的类是很难管理的,对我来说似乎很浪费.
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.
有时,我可能还需要向数据添加某种最小功能.在示例中,假设我有时也需要年龄,基于 dob:
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:
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.
推荐答案
我认为这里有两个重要的设计原则需要考虑:
I think there are two important design principles to consider here:
如果该类有一些不变性,则通过接口隐藏该类的表示.
当该类存在无效状态时,该类具有不变量.类应始终保持不变.
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.
考虑表示二维几何点的 Point
类型.这应该只是一个带有公共 x
和 y
数据成员的 struct
.没有无效点这样的东西.x
和 y
值的每个组合都非常好.
Consider a Point
type that represents a 2D geometric point. This should just be a struct
with public x
and y
data members. There is no such thing as an invalid point. Every combination of x
and y
values is perfectly fine.
对于Person
,它是否有不变量完全取决于手头的问题.您认为空名称之类的东西是有效名称吗?Person
可以有任何出生日期吗?对于你的情况,我认为答案是肯定的,你的班级应该让成员公开.
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 the Person
have any date of birth? For your case, I think the answer is yes and your class should keep the members public.
参见:类应该强制执行不变量
非友元非成员函数改进封装.
没有理由将您的 age
函数实现为成员函数.age
的结果可以通过Person
的公共接口计算出来,所以没有理由成为成员函数.将它放在与 Person
相同的命名空间中,以便通过依赖于参数的查找找到它.ADL 找到的函数是该类接口的一部分;他们只是无权访问私人数据.
There's no reason your age
function should be implemented as a member function. The result of age
can be calculated using the public interface of Person
, so it has no reason to be a member function. Place it in the same namespace as Person
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.
如果您确实将其设为成员函数,并且有一天向Person
引入了一些私有状态,那么您将拥有不必要的依赖项.突然 age
获得了比它需要的更多的数据访问权限.
If you did make it a member function and one day introduced some private state to Person
, you would have an unnecessary dependency. Suddenly age
has more access to data than it needs.
参见:非成员函数如何改进封装p>
所以这是我将如何实现它:
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;
}
相关文章