C++ 公共变量坏习惯vs getter和setter函数?

C++ 公共变量坏习惯vs getter和setter函数?,c++,C++,我是在他的溪流中遇到这个的,从那以后,我就觉得这个很难受。我想,如果我保存了视频,以后当我更熟练的时候再回来看,我会理解它,但它只是一直困扰着我不去看它。这是视频 它会在1:13:00为您自动启动 作为一名新的C/C++程序员,听了这番话后,我的思维方式完全扭曲了。他是一名专业人士,我应该接受他的建议,但我需要澄清一下。从网站、视频到书籍,我都读到使用公共变量是一种不好的做法,但从我从这段视频中得到的信息来看,这是另一种说法。在视频中,他使用了一个默认访问修饰符为“public”的结构,而不是

我是在他的溪流中遇到这个的,从那以后,我就觉得这个很难受。我想,如果我保存了视频,以后当我更熟练的时候再回来看,我会理解它,但它只是一直困扰着我不去看它。这是视频

它会在1:13:00为您自动启动

作为一名新的C/C++程序员,听了这番话后,我的思维方式完全扭曲了。他是一名专业人士,我应该接受他的建议,但我需要澄清一下。从网站、视频到书籍,我都读到使用公共变量是一种不好的做法,但从我从这段视频中得到的信息来看,这是另一种说法。在视频中,他使用了一个默认访问修饰符为“public”的结构,而不是一个默认访问权限为“private”的类。这里有什么我没有完全理解的


我不知道该怎么办。如果我公开我的变量,我不会冒歧义的风险吗?他说他会自动解雇一个按格式编码的人,这让我很吃惊,哈哈!我应该真正使用哪一种?何时以及为什么?

如果将数据成员公开,则很难控制对象的内部一致性

有效的方法是使用构造函数设置对象的状态,然后使用公共函数检索成员变量的值,但只有在需要时才这样做。如果您需要在构建后对对象进行变异,那么请为此提供非常具体的方法

但是,如果您的对象只不过是聚合正交数据类型的对象,那么对所有成员使用公共访问:
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在您希望避免在不受任何控制的情况下对成员进行修改时非常有用。我认为这有点过度使用,有些情况下公共变量是可以接受的,但对于