‫所以我们知道我们的基类需要一些组件｡
‫我们知道, 我们需要一个基础网格的底部部分的坦克和炮塔｡
‫我们还需要一个炮塔网格的顶部部分｡
‫我们需要一个胶囊来处理碰撞, 我们需要一个投射产卵点｡
‫这将是一个场景组件｡
‫现在, 一旦我们将这些内容添加到基本pod类中, 那么我们基于该类创建的任何内容都将继承这些内容｡
‫所以我们可以根据基地建造一个坦克——然后我们可以根据基地建造一个塔——｡
‫因为它们基于基本pod, 所以它们继承了这些组件｡
‫坦克可以有自己的基础网, 自己的炮塔网, 自己的胶囊和自己的炮弹产卵点｡
‫同样, 塔将得到自己的基地网炮塔网胶囊组件和炮弹产卵点以及｡
‫我们很快就会看到我们如何为每一个网格分配不同的网格, 使它们看起来不同｡
‫所以我们知道我们需要一些组件｡
‫现在是时候向我们的基类添加一些组件了｡
‫现在, 默认情况下, 我们已经有了一个公共部分､ 一个受保护部分和下面的第二个公共部分｡
‫拥有多个公共部分的原因有很多, 我们稍后会讨论这些原因｡
‫但是对于我们的组件, 我们将创建一个私有部分｡
‫正如您在前面所了解到的, 让成员变量成为私有变量是很好的,
‫这样它们只能从拥有它们的类中访问｡
‫所以我们需要一些部件｡
‫我首先要说的是胶囊｡
‫因此, 让我们创建一个类型为capsule component的变量｡
‫这是一个指针｡
‫我们将对大多数变量使用指针, 只要它们不是整型或浮点型.
‫如你所知, 这是因为指针是轻量级的, 它们只是地址, 它们让我们更有效率｡
‫我们有一个U封装组件指针, 我们将把这个封装组件称为封装组件的简称｡
‫现在就在capsule组件上面, 我们将添加一个不真实的引擎特定宏, 它是用括号括起来的全部大写的you属性｡
‫你的属性是一种让虚幻引擎意识到这个变量的方法, 这样它就可以参与虚幻引擎｡
‫反射系统｡
‫反射系统允许我们做一些事情, 比如将这个变量公开给蓝图, 参与垃圾收集等等｡
‫因此, 添加you属性将在我们创建组件时添加到组件中｡
‫所以我们有这个封装组件, 因为我们使用YOU封装组件类型,
‫我们需要让编译器知道这个类型｡
‫默认情况下, 它不知道什么是胶囊组件｡
‫现在通常告诉编译器什么是封装组件, 我们会在顶部包含一个头文件,
‫如果我们转到unreal引擎文档,
‫搜索封装组件, 我们可以看到这里写着包含头文件, 我们需要包含它来告诉编译器关于封装组件的信息｡
‫现在我们可以把这个放在顶部, 然后我们的U｡
‫胶囊组件类型将被编译器识别, 一切都将是hunky dory｡
‫但是, 一般来说, 在编写这些代码时, 最好的做法是尽量使头文件尽可能小｡
‫每当我们在这个文件中包含一个头文件时,
‫一个叫做预处理器的程序会提取这个头文件的所有内容, 去掉一些像注释这样的东西, 然后把这个头文件的所有内容粘贴到这个文件中｡
‫结果是这个文件变大了, 因为它有包括的文件的内容粘贴在这里｡
‫我们只想在使用的时候包含一些东西｡
‫那么我们如何避免在基本头文件中不包含头文件呢？
‫我们可以使用C++中的一种方法, 叫做前向声明｡
‫我们使用class关键字向前声明这个u capsule组件类型, 如下所示｡
‫请注意, 编译器现在将此类型显示为绿色, 无论何时我们正向声明一个变量,
‫然后就可以不包括其头文件｡
‫它告诉编译器这是一个类型, 因此它不再向我们提供IntelliSense错误, 即它不将此识别为类型｡
‫这是一个不完整的类型｡
‫如果我们实际上试图通过访问成员（如函数和变量）来使用此类型, 或者试图构造此类型的对象, 我们将得到一个错误,
‫因为它是一个不完整的类型｡
‫我们需要在使用该类型的任何地方包含头文件, 这样我们就可以向前声明一个类型的指针,
‫以避免需要头文件｡
‫但是需要注意的是, 我们确实需要头文件来继承特定的类｡
‫请注意, 此类继承自池塘, 池塘头文件包含在顶部｡
‫因此继承确实需要我们从其继承的类型的头文件｡
‫那么, 让我们来讨论一下前向声明, 以及为什么要这样做｡
‫假设我们有一个名为Base Pon的类, 它需要一个封装组件的指针变量｡
‫现在你的胶囊组件就在胶囊组件头文件中｡
‫现在我们要使用这个类型, 当我们构造一个U的对象时｡
‫胶囊组件类型｡
‫所以在中, 我们真正需要的基础是有一个U型指针的封装组件｡
‫现在的事实是基于H实际上并不需要封装组件类的实现细节｡
‫换句话说, 它不需要知道函数是如何定义的, 甚至不需要知道封装组件类有多大｡
‫胶囊组件指针的大小与任何其他指针相同｡
‫只是个地址｡
‫现在在基地计划班｡
‫我们要构建胶囊组件｡
‫因此, 我们需要知道胶囊组件的大小, 以便为创建该对象分配所需的内存｡
‫因此, 虽然胶囊组件头在基本庞卡中不是严格需要的, 但在基本庞卡中绝对需要｡
‫好的编程实践是只在真正需要的地方包含头文件, 这样我们就不用在基础产品H中声明U类型的指针,
‫然后在需要实现细节的地方包含胶囊组件,
‫因为我们要构造一个胶囊组件, 我们需要知道的大小｡
‫内存中的胶囊组件｡
‫现在, 让我们讨论一下将头文件包含在base pond FX中的后果｡
‫正如我们所看到的, 我们完全可以做到这一点, 你可能会想, 好吧,
‫我们把它包括在基点CP中, 不管怎样, 如果我们把它包括在一个文件中, 和另一个文件中, 有什么区别呢？
‫现在问题来了｡
‫头文件设计为包含在其他文件中｡
‫假设我们有一个基础池H, 其中包含胶囊组件｡
‫接下来我们会有其他类, 我们会在其他类中有一个基池指针,
‫就像我们在基容器中有一个胶囊组件指针一样.
‫现在, 我们不需要麻烦地向前声明base
‫pond指针和其他类, 我们只需要声明它为normal, 并将base pawn包含在其他类中.
‫因此, 现在不仅Base Pond H包含了capsule组件头文件, 这会导致更多的代码被复制到该头文件中｡
‫现在其他一些类有了基础, 其中包括封装组件｡
‫所以所有的内容和胶囊组件也在其他一些H类中, 那里甚至不需要｡
‫H只需要知道一些其他的类, 因为它不关心封装组件｡
‫现在假设我们继续这个模式, 创建另一个类, 称为另一个类, 另一个类可能需要一个指针,
‫类型是另一个类, 而不是前向声明｡
‫我们只是把另一个类H包含在另一个类H中, 现在又包含在另一个类H中｡
‫尽管我们甚至不需要基池或封装组件H的头文件, 但我们还是在另一个类中得到了它,
‫因为其他一些类在其中包含了这些头文件｡
‫所以我们有所有封装组件内容的副本, 基于H, 只是在这里, 又被卡在了另一个类中,
‫文件膨胀, 编译时间增加, 都是因为我们没有向前声明｡
‫因此, 更好的做法是在实际需要的地方包含头文件｡
‫因此, 如果我们采用封装组件并仅将其包含在based on
‫CPP中, 那么以后当我们创建其他类并实际需要使用基本pod时,
‫我们可以在其中包含头部, 而based on不包含封装组件, 因此所有额外的代码都不会包含在其他类中｡
‫然后当我们创建另一个类, 它需要其他的类时, 我们可以在另一个类中包含其他的类,
‫在CPP中, 实际需要的地方, 然后另一个类,
‫H不会被其他不需要的头文件的内容填充｡
‫因此, 当类具有依赖关系时, 最好将这些依赖关系保持在最低限度｡
‫所以我要挑战你去创造一个编译错误｡
‫我们不应该害怕编译错误｡
‫它们只是开发过程中的一个正常部分｡
‫所以我们会有意地生成一个, 返回并删除class关键字, 然后在不向前声明capsule comp的情况下进行编译｡
‫现在, 当我说编译时, 我的意思是你可以从Visual Studio代码编译, 只是一个常规的C++编译｡
‫您已经学习了如何执行此操作, 或者您可以简单地保存和Visual Studio代码并启动实时编码｡
‫这两种方法都可以, 一旦我们一起完成了这一步, 我将向您展示这两种方法的效果｡
‫如果您使用实时编码, 当然您将在实时编码窗口中看到生成的输出, 而不是在Visual
‫Studio代码中看到的输出｡
‫剧透一下, 你会得到一个编译错误, 看看编译错误信息, 看看它告诉你什么｡
‫这只是让我们熟悉一下我们产生的错误｡
‫然后, 在这之后, 返回并前进, 使用class关键字声明capsule comp｡
‫一旦你完成了, 再编译一次, 这次你应该会得到一个成功的编译｡
‫暂停视频, 给予｡
‫好吧, 让我们在这里对代码进行一些破坏｡
‫我将删除class关键字｡
‫好的, 我们已经尝试编译了, 这是终端的输出｡
‫我们看到的第一件事是错误, 它给了我们一个错误代码, 它说胶囊comp不是基地兵的成员｡
‫我们有一个注释, 说C声明了一个基本兵, 然后我们看到我们得到了其他错误作为这个结果｡
‫因此, 学生在尝试编译时往往会感到困惑, 似乎有多个错误｡
‫这表明一个错误可以传播一系列错误｡
‫这并不意味着你必须去修复一大堆文件｡
‫该错误可能在此处有一个单一的起源｡
‫我们知道错误的根源是什么｡
‫我们需要向前声明｡
‫现在, 让我们看看如果使用实时编码而不是常规编译和Visual Studio代码会发生什么｡
‫接下来, 我将单击该按钮启动实时编码, 然后立即以红色显示构建失败,
‫我们在这里看到了相同的内容｡
‫就在这里｡
‫封壳组件不是基本兵注释的成员｡
‫见《贱卒宣言》｡
‫所以我们在这里看到了同样的事情｡
‫所以不管是哪种情况, 我们都会看到这样的错误, 当我们忘记forward声明的时候｡
‫所以现在我们知道了它的样子, 现在我们更了解这些神秘的编译错误消息, 也更少了恐惧｡
‫所以我们要做的就是通过前向声明你的封装组件来修复这个错误, 然后我们可以尝试再次编译｡
‫现在我们已经编译完成, 没有任何错误｡
‫现在我们看到了当我们忘记正向声明一个变量时的情况｡
‫以后遇到编译器错误时请记住这一点｡
‫总之, 我们讨论了创建新指针时的前向声明,
‫我们了解到, 应该只包含CP文件中使用的内容, 而在H文件中应尽可能少地包含｡
‫我们知道, 只要我们正向声明, 就不需要头文件来声明一个新的指针,
‫如果我们要构造一个特定类型的对象, 就需要头文件.
‫我们确实需要头文件来访问成员, 比如函数和变量, 我们看到,
‫我们确实需要头文件来继承, 从类继承｡
‫我们需要那个头文件｡
‫现在我们知道了如何正向声明一个类型, 我们有了指针capsule组件, 我们已经准备好实际构造一个capsule组件对象,
‫我们将在下一个视频中进行｡
‫我很快就会见到你的｡