C++ 公共变量坏习惯vs getter和setter函数?
我是在他的溪流中遇到这个的,从那以后,我就觉得这个很难受。我想,如果我保存了视频,以后当我更熟练的时候再回来看,我会理解它,但它只是一直困扰着我不去看它。这是视频 它会在1:13:00为您自动启动 作为一名新的C/C++程序员,听了这番话后,我的思维方式完全扭曲了。他是一名专业人士,我应该接受他的建议,但我需要澄清一下。从网站、视频到书籍,我都读到使用公共变量是一种不好的做法,但从我从这段视频中得到的信息来看,这是另一种说法。在视频中,他使用了一个默认访问修饰符为“public”的结构,而不是一个默认访问权限为“private”的类。这里有什么我没有完全理解的C++ 公共变量坏习惯vs getter和setter函数?,c++,C++,我是在他的溪流中遇到这个的,从那以后,我就觉得这个很难受。我想,如果我保存了视频,以后当我更熟练的时候再回来看,我会理解它,但它只是一直困扰着我不去看它。这是视频 它会在1:13:00为您自动启动 作为一名新的C/C++程序员,听了这番话后,我的思维方式完全扭曲了。他是一名专业人士,我应该接受他的建议,但我需要澄清一下。从网站、视频到书籍,我都读到使用公共变量是一种不好的做法,但从我从这段视频中得到的信息来看,这是另一种说法。在视频中,他使用了一个默认访问修饰符为“public”的结构,而不是
我不知道该怎么办。如果我公开我的变量,我不会冒歧义的风险吗?他说他会自动解雇一个按格式编码的人,这让我很吃惊,哈哈!我应该真正使用哪一种?何时以及为什么?如果将数据成员公开,则很难控制对象的内部一致性 有效的方法是使用构造函数设置对象的状态,然后使用公共函数检索成员变量的值,但只有在需要时才这样做。如果您需要在构建后对对象进行变异,那么请为此提供非常具体的方法 但是,如果您的对象只不过是聚合正交数据类型的对象,那么对所有成员使用公共访问:
struct
可以很好地实现这一点
请注意,
struct
和class
之间的唯一区别在于,在前者中,默认访问是public
,而在后者中,它是private
,根据我的经验,人们过度使用getter/setter是没有充分理由的
我们可以想到两种主要的类:将相关数据分组的类和提供行为的类
行为类必须封装为没有公共数据成员的类
数据类通常应该具有公共的数据成员,并且没有行为
这两者之间的灰色区域是可变数据类,具有不变量或成员之间的依赖关系,例如,如果成员
a
为1,则成员b
必须在范围[1-10]
内。对于这种情况,使用getter/setter可能是合理的。对于不可变的数据类,构造函数必须建立不变量。如果您将数据成员保持为私有,则可以轻松控制对其值的访问。例如,代码中有age
变量
public:
int age;
现在,你班以外的人可以很容易地更改年龄值,也可以指定非法值,例如age=-10
。但你们的逻辑表明年龄不能是负的,所以最好的做法是保持变量私有,并给出一些函数来为变量赋值
private:
int age;
public:
void setAge(int age)
{
if (age > 0)
this->age = age;
}
首先,
struct
完全等同于类
,但默认成员访问权限是public
,而不是private
现在,在面向对象编程(OOP)中,拥有公共
数据成员(变量)被认为是不好的做法,因为这使得所有代码都依赖于类
的内部,从而打破了OOP的一个基本原则,即
神圣和神圣的封装
封装是一种编码哲学,它指出类应该在一个紧密的实体中同时包含数据和管理数据的代码。也就是说,您不直接访问数据,而是使用类中的方法来操作这些数据。这有几个设计优势,例如,您将知道,除了类中的代码外,没有任何代码会包含与此类信息操作相关的bug
现在,get()!有了访问器,当您相当破坏它时,您就在欺骗自己,让自己认为您尊重封装!它增加了膨胀、不必要的冗长、bug以及除封装之外的所有内容。不要让类人物带有无符号getAge()
和无效设置(无符号)
,而是让它带有无符号getAge()
和无效增量()
或您想如何调用它
现在,到你问题的核心
“普通旧”结构
封装并不总是需要的。尽管您(通常)不应该在头文件上执行此操作(同样,至少对于一些封装),但您可以创建单个翻译单元专用的静态普通旧结构。我的建议是让他们比现在更“老”,即
- 所有数据成员都是
公共的
- 没有办法
- 没有构造函数(隐式构造函数除外)
- 继承始终是公共的,并且只允许从其他普通的旧
struct
s继承
- 我重复一遍,不要将它们放在头文件中李>
现在,普通的struct
s的另一个用途是(具有讽刺意味的)元编程导出constepr
数据和类型,或者称为现代硬核模板元编程,而不必到处键入-public
,例如
template<bool B, typename T>
struct EnableIf {};
template<typename T>
struct EnableIf<true, T> {
typedef T type;
};
template<bool B, typename T>
using SFINAE = typename EnableIf<B, T>::Type;
模板
结构启用If{};
模板
结构启用码{
T型;
};
模板
使用SFINAE=typename EnableIf::Type;
getter和setter在您希望避免在不受任何控制的情况下对成员进行修改时非常有用。我认为这有点过度使用,有些情况下公共变量是可以接受的,但对于