1. 概述
类和结构体有什么区别呢,上篇中我们讲到类,对类有了一些基本的了解。这篇我们来看看类和结构体
基本上我们有两个术语,结构体struct(structure的缩写),以及类class。这两个看起来有点相似,很多人有点困惑这两个到底有什么区别?我们到底应该是使用struct还是使用class?
2. 案例
可以说,这两个基本上没什么区别,只有一个关于可见度的小区别。上一篇中有说过,一个类的成员,默认为private,这意味着如果我们想通过对象去调用方法或属性时,要在类中声明这些方法和属性为public。
如果我们去掉public
可以看到VS会给我们提示一个错误,可以看到move函数声明了,但是不能访问,这是因为,类中的方法默认被标记为private,私有的。意思是只有在类里面的其他方法才能访问这个move方法。这就是为什么我们必须要加上public的原因
这就是区别的本质所在,默认情况下,类是私有的,所以如果我们不指定修改任何可见性,就像我们移除public,然后不指定任何东西,那默认值就是私有的,private的。
在结构体struct中,默认值确是public。从技术上讲,这是类和结构体的唯一区别。我们可以在代码中看到,现在VS是给了错误提示,不让我们在类外面调用类的私有方法,因为在类的外面,私有方法是不可访问的。
然而,我们将class改为struct,将类改为结构体
可以看到,VS的错误提示消失了。
如果我们想让struct结构体中某些东西私有。我们也可以明确的写上private。
可以看到,加上private后,VS又给了我们一个错误提示。
以上就是类class和结构体struct的区别。然而,这只是技术上讲的区别。
下面,我们来谈谈如何定义这两个词之间的区别。
struct结构体在C++中继续存在的唯一原因,是因为C++希望与C保持向后兼容性,因为C代码没有类,但是C代码有结构体。如果C++突然去掉整个结构体关键字,那么C++会失去兼容性,因为如果去掉,C++编译器会不知道什么是struct。当然,C++编译器也可以很容易解决这个问题,只需要使用#define来查找,我们可以写一些类似#define的东西。#define struct class,这主要做的就是用class替换所有的struct。如下
可以看到VS又给出了错误提示。尽管我们用的struct这个词,但是我们#define struct class这里用class替换了struct,虽然这样做,也许能得到C、C++的某种兼容性,但不理想,因为理想情况下,应该做到C语言的struct替换成class,然后将其默认访问变成public,这样才能保持与C中的struct一致。
这就是struct和class的区别了,在实际情况中不会有更多的区别了,所以语义上的不用以及人们如何看待它,或多或少取决于用法。如果没有区别,那什么时候使用struct,什么时候使用class,如果我想要所有的成员都是公共的,而又不想写public关键字,我应该使用struct结构体吗?真的就这点需求吗?是的,它就是这么微不足道的需求。正因如此,人们都有自己对于struct以及class的理解和定义。而且,没有什么正确或错误的答案,这取决我们的编程风格。
下面来谈谈一个游戏大神的编程风格,以及可能在哪里使用哪种类型,当我们谈论到POD(Plain old data)时,我喜欢尽可能的使用struct,我说的是一种只表示变量的结构,一堆变量,仅此而已。这方面的一个很好的例子可能是数学上的向量类。
如下,我想做一种struct,把两个浮点数搞到一起,我们可以把它定义为一个结构,有x和y两个浮点数
不管是用class还是struct,都是代表这2个浮点数的一种结构,这就是它的核心。它不应该像之前的Player类一样包含大量功能,这个Player类,可能有一个3D模型,它可能会为这个3D模型处理渲染代码,它可能处理比如player如何在地图上移动,并接受键盘输入等等,可能会有很多功能。而我们这里的这个结构vec2,它只有两个变量,我们把它们分组只是为了让我们的代码更容易使用,这就是我们所做的。当然这并不是说,我不会添加方法到struct里面,其实也完全可以。例如,我可能添加一个add方法,取另一个vec2作为参数,然后在方法里面做相加处理,如下
但是再说一次,我在这里做的是,我只是在处理这些变量,只是添加了一个函数来处理这些变量,到最后,我们仍然只讨论这两个变量。当然,如果我们真的要深入进去并认真思考,你可能会说,Player类不也只是操作这些变量吗?其实在设计上还是有一点不同的,因为我们讨论的东西要复杂得多。
另外的场景就是继承,我不会在struct中使用继承,如果我要有一个完整的类层次结构,或者某种继承层次结构,那么我将使用类,因为继承是一种增加另一层次复杂性的东西。我只希望我的结构体,是数据的结构,仅此而已。
除此之外,如果你尝试混合使用这些类型。举个例子,我们有一个叫做a的类和一个叫做b的结构体。这个b的结构体继承自类a,那么某些编译器会警告,告诉结构体b你继承了一个类a,但是你是结构体。虽然这里有警告,但是程序仍然可以运行,只是有一点语义上的不同。在这里,我们使用结构体而不是类的原因是如果我只是想用结构体表示一些数据,我将使用一个结构体,但如果我想要一个大量功能的整个类,比如一个游戏世界,或者一个Player,或者其他可能有需要继承的东西,所有这些系统,我将使用一个类。这也是这个游戏大神个人区分这两种类型的方法,也是他在这个行业看到的很多人如何区分这两种类型。再说一次,技术上,struct和class没有区别,除了可见性,我们可以在任何可以使用类的地方使用结构体,它们将以相同的方式工作。