﻿1
00:00:04,470 --> 00:00:08,280
‫所以我们知道我们的基类需要一些组件｡

2
00:00:08,280 --> 00:00:12,570
‫我们知道, 我们需要一个基础网格的底部部分的坦克和炮塔｡

3
00:00:12,600 --> 00:00:15,270
‫我们还需要一个炮塔网格的顶部部分｡

4
00:00:15,300 --> 00:00:19,500
‫我们需要一个胶囊来处理碰撞, 我们需要一个投射产卵点｡

5
00:00:19,500 --> 00:00:21,270
‫这将是一个场景组件｡

6
00:00:21,300 --> 00:00:28,320
‫现在, 一旦我们将这些内容添加到基本pod类中, 那么我们基于该类创建的任何内容都将继承这些内容｡

7
00:00:28,320 --> 00:00:35,550
‫所以我们可以根据基地建造一个坦克——然后我们可以根据基地建造一个塔——｡

8
00:00:35,700 --> 00:00:39,620
‫因为它们基于基本pod, 所以它们继承了这些组件｡

9
00:00:39,630 --> 00:00:46,800
‫坦克可以有自己的基础网, 自己的炮塔网, 自己的胶囊和自己的炮弹产卵点｡

10
00:00:46,800 --> 00:00:53,370
‫同样, 塔将得到自己的基地网炮塔网胶囊组件和炮弹产卵点以及｡

11
00:00:53,370 --> 00:00:58,560
‫我们很快就会看到我们如何为每一个网格分配不同的网格, 使它们看起来不同｡

12
00:00:58,560 --> 00:01:00,750
‫所以我们知道我们需要一些组件｡

13
00:01:00,750 --> 00:01:05,490
‫现在是时候向我们的基类添加一些组件了｡

14
00:01:05,910 --> 00:01:12,240
‫现在, 默认情况下, 我们已经有了一个公共部分､ 一个受保护部分和下面的第二个公共部分｡

15
00:01:12,570 --> 00:01:17,520
‫拥有多个公共部分的原因有很多, 我们稍后会讨论这些原因｡

16
00:01:17,520 --> 00:01:20,880
‫但是对于我们的组件, 我们将创建一个私有部分｡

17
00:01:22,070 --> 00:01:28,400
‫正如您在前面所了解到的, 让成员变量成为私有变量是很好的,

18
00:01:28,400 --> 00:01:31,790
‫这样它们只能从拥有它们的类中访问｡

19
00:01:31,790 --> 00:01:33,410
‫所以我们需要一些部件｡

20
00:01:33,680 --> 00:01:36,190
‫我首先要说的是胶囊｡

21
00:01:36,200 --> 00:01:40,760
‫因此, 让我们创建一个类型为capsule component的变量｡

22
00:01:42,160 --> 00:01:44,030
‫这是一个指针｡

23
00:01:44,070 --> 00:01:50,340
‫我们将对大多数变量使用指针, 只要它们不是整型或浮点型.

24
00:01:50,350 --> 00:01:56,860
‫如你所知, 这是因为指针是轻量级的, 它们只是地址, 它们让我们更有效率｡

25
00:01:56,950 --> 00:02:04,030
‫我们有一个U封装组件指针, 我们将把这个封装组件称为封装组件的简称｡

26
00:02:04,030 --> 00:02:14,020
‫现在就在capsule组件上面, 我们将添加一个不真实的引擎特定宏, 它是用括号括起来的全部大写的you属性｡

27
00:02:14,020 --> 00:02:20,980
‫你的属性是一种让虚幻引擎意识到这个变量的方法, 这样它就可以参与虚幻引擎｡

28
00:02:20,980 --> 00:02:22,240
‫反射系统｡

29
00:02:22,690 --> 00:02:31,060
‫反射系统允许我们做一些事情, 比如将这个变量公开给蓝图, 参与垃圾收集等等｡

30
00:02:31,060 --> 00:02:36,400
‫因此, 添加you属性将在我们创建组件时添加到组件中｡

31
00:02:36,400 --> 00:02:41,980
‫所以我们有这个封装组件, 因为我们使用YOU封装组件类型,

32
00:02:41,980 --> 00:02:44,860
‫我们需要让编译器知道这个类型｡

33
00:02:44,860 --> 00:02:48,250
‫默认情况下, 它不知道什么是胶囊组件｡

34
00:02:48,250 --> 00:02:54,640
‫现在通常告诉编译器什么是封装组件, 我们会在顶部包含一个头文件,

35
00:02:54,640 --> 00:02:59,680
‫如果我们转到unreal引擎文档,

36
00:02:59,710 --> 00:03:08,950
‫搜索封装组件, 我们可以看到这里写着包含头文件, 我们需要包含它来告诉编译器关于封装组件的信息｡

37
00:03:08,950 --> 00:03:13,000
‫现在我们可以把这个放在顶部, 然后我们的U｡

38
00:03:13,000 --> 00:03:18,160
‫胶囊组件类型将被编译器识别, 一切都将是hunky dory｡

39
00:03:18,220 --> 00:03:25,720
‫但是, 一般来说, 在编写这些代码时, 最好的做法是尽量使头文件尽可能小｡

40
00:03:25,720 --> 00:03:32,380
‫每当我们在这个文件中包含一个头文件时,

41
00:03:32,380 --> 00:03:40,780
‫一个叫做预处理器的程序会提取这个头文件的所有内容, 去掉一些像注释这样的东西, 然后把这个头文件的所有内容粘贴到这个文件中｡

42
00:03:41,050 --> 00:03:47,530
‫结果是这个文件变大了, 因为它有包括的文件的内容粘贴在这里｡

43
00:03:47,530 --> 00:03:50,950
‫我们只想在使用的时候包含一些东西｡

44
00:03:50,950 --> 00:03:56,740
‫那么我们如何避免在基本头文件中不包含头文件呢？

45
00:03:56,740 --> 00:04:02,380
‫我们可以使用C++中的一种方法, 叫做前向声明｡

46
00:04:02,380 --> 00:04:07,990
‫我们使用class关键字向前声明这个u capsule组件类型, 如下所示｡

47
00:04:08,470 --> 00:04:15,310
‫请注意, 编译器现在将此类型显示为绿色, 无论何时我们正向声明一个变量,

48
00:04:15,310 --> 00:04:18,010
‫然后就可以不包括其头文件｡

49
00:04:18,010 --> 00:04:26,170
‫它告诉编译器这是一个类型, 因此它不再向我们提供IntelliSense错误, 即它不将此识别为类型｡

50
00:04:26,170 --> 00:04:28,150
‫这是一个不完整的类型｡

51
00:04:28,150 --> 00:04:34,150
‫如果我们实际上试图通过访问成员（如函数和变量）来使用此类型, 或者试图构造此类型的对象, 我们将得到一个错误,

52
00:04:34,150 --> 00:04:38,560
‫因为它是一个不完整的类型｡

53
00:04:38,560 --> 00:04:44,950
‫我们需要在使用该类型的任何地方包含头文件, 这样我们就可以向前声明一个类型的指针,

54
00:04:44,950 --> 00:04:48,400
‫以避免需要头文件｡

55
00:04:48,400 --> 00:04:53,230
‫但是需要注意的是, 我们确实需要头文件来继承特定的类｡

56
00:04:53,230 --> 00:05:00,130
‫请注意, 此类继承自池塘, 池塘头文件包含在顶部｡

57
00:05:00,130 --> 00:05:05,470
‫因此继承确实需要我们从其继承的类型的头文件｡

58
00:05:05,470 --> 00:05:09,100
‫那么, 让我们来讨论一下前向声明, 以及为什么要这样做｡

59
00:05:09,130 --> 00:05:17,020
‫假设我们有一个名为Base Pon的类, 它需要一个封装组件的指针变量｡

60
00:05:17,050 --> 00:05:22,060
‫现在你的胶囊组件就在胶囊组件头文件中｡

61
00:05:22,060 --> 00:05:28,470
‫现在我们要使用这个类型, 当我们构造一个U的对象时｡

62
00:05:28,480 --> 00:05:30,010
‫胶囊组件类型｡

63
00:05:30,010 --> 00:05:36,820
‫所以在中, 我们真正需要的基础是有一个U型指针的封装组件｡

64
00:05:37,000 --> 00:05:45,160
‫现在的事实是基于H实际上并不需要封装组件类的实现细节｡

65
00:05:45,160 --> 00:05:51,820
‫换句话说, 它不需要知道函数是如何定义的, 甚至不需要知道封装组件类有多大｡

66
00:05:51,850 --> 00:05:55,750
‫胶囊组件指针的大小与任何其他指针相同｡

67
00:05:55,750 --> 00:05:57,250
‫只是个地址｡

68
00:05:57,250 --> 00:05:58,810
‫现在在基地计划班｡

69
00:05:58,810 --> 00:06:01,420
‫我们要构建胶囊组件｡

70
00:06:01,510 --> 00:06:09,790
‫因此, 我们需要知道胶囊组件的大小, 以便为创建该对象分配所需的内存｡

71
00:06:09,790 --> 00:06:16,330
‫因此, 虽然胶囊组件头在基本庞卡中不是严格需要的, 但在基本庞卡中绝对需要｡

72
00:06:16,350 --> 00:06:24,970
‫好的编程实践是只在真正需要的地方包含头文件, 这样我们就不用在基础产品H中声明U类型的指针,

73
00:06:24,970 --> 00:06:32,410
‫然后在需要实现细节的地方包含胶囊组件,

74
00:06:32,410 --> 00:06:41,020
‫因为我们要构造一个胶囊组件, 我们需要知道的大小｡

75
00:06:41,310 --> 00:06:43,230
‫内存中的胶囊组件｡

76
00:06:43,350 --> 00:06:49,920
‫现在, 让我们讨论一下将头文件包含在base pond FX中的后果｡

77
00:06:50,010 --> 00:06:55,410
‫正如我们所看到的, 我们完全可以做到这一点, 你可能会想, 好吧,

78
00:06:55,410 --> 00:07:01,230
‫我们把它包括在基点CP中, 不管怎样, 如果我们把它包括在一个文件中, 和另一个文件中, 有什么区别呢？

79
00:07:01,260 --> 00:07:03,180
‫现在问题来了｡

80
00:07:03,210 --> 00:07:07,390
‫头文件设计为包含在其他文件中｡

81
00:07:07,410 --> 00:07:12,810
‫假设我们有一个基础池H, 其中包含胶囊组件｡

82
00:07:12,810 --> 00:07:18,600
‫接下来我们会有其他类, 我们会在其他类中有一个基池指针,

83
00:07:18,600 --> 00:07:23,370
‫就像我们在基容器中有一个胶囊组件指针一样.

84
00:07:23,400 --> 00:07:28,230
‫现在, 我们不需要麻烦地向前声明base

85
00:07:28,230 --> 00:07:33,810
‫pond指针和其他类, 我们只需要声明它为normal, 并将base pawn包含在其他类中.

86
00:07:34,680 --> 00:07:43,190
‫因此, 现在不仅Base Pond H包含了capsule组件头文件, 这会导致更多的代码被复制到该头文件中｡

87
00:07:43,200 --> 00:07:47,820
‫现在其他一些类有了基础, 其中包括封装组件｡

88
00:07:47,820 --> 00:07:56,400
‫所以所有的内容和胶囊组件也在其他一些H类中, 那里甚至不需要｡

89
00:07:56,400 --> 00:08:01,910
‫H只需要知道一些其他的类, 因为它不关心封装组件｡

90
00:08:01,920 --> 00:08:07,920
‫现在假设我们继续这个模式, 创建另一个类, 称为另一个类, 另一个类可能需要一个指针,

91
00:08:07,920 --> 00:08:13,680
‫类型是另一个类, 而不是前向声明｡

92
00:08:13,680 --> 00:08:21,180
‫我们只是把另一个类H包含在另一个类H中, 现在又包含在另一个类H中｡

93
00:08:21,210 --> 00:08:27,840
‫尽管我们甚至不需要基池或封装组件H的头文件, 但我们还是在另一个类中得到了它,

94
00:08:27,840 --> 00:08:32,730
‫因为其他一些类在其中包含了这些头文件｡

95
00:08:32,730 --> 00:08:40,140
‫所以我们有所有封装组件内容的副本, 基于H, 只是在这里, 又被卡在了另一个类中,

96
00:08:40,140 --> 00:08:46,620
‫文件膨胀, 编译时间增加, 都是因为我们没有向前声明｡

97
00:08:46,620 --> 00:08:52,440
‫因此, 更好的做法是在实际需要的地方包含头文件｡

98
00:08:52,440 --> 00:08:59,610
‫因此, 如果我们采用封装组件并仅将其包含在based on

99
00:08:59,610 --> 00:09:05,340
‫CPP中, 那么以后当我们创建其他类并实际需要使用基本pod时,

100
00:09:05,340 --> 00:09:13,440
‫我们可以在其中包含头部, 而based on不包含封装组件, 因此所有额外的代码都不会包含在其他类中｡

101
00:09:13,440 --> 00:09:18,810
‫然后当我们创建另一个类, 它需要其他的类时, 我们可以在另一个类中包含其他的类,

102
00:09:18,810 --> 00:09:24,990
‫在CPP中, 实际需要的地方, 然后另一个类,

103
00:09:24,990 --> 00:09:30,270
‫H不会被其他不需要的头文件的内容填充｡

104
00:09:30,270 --> 00:09:38,670
‫因此, 当类具有依赖关系时, 最好将这些依赖关系保持在最低限度｡

105
00:09:38,880 --> 00:09:42,570
‫所以我要挑战你去创造一个编译错误｡

106
00:09:42,570 --> 00:09:44,970
‫我们不应该害怕编译错误｡

107
00:09:44,970 --> 00:09:47,550
‫它们只是开发过程中的一个正常部分｡

108
00:09:47,550 --> 00:09:56,160
‫所以我们会有意地生成一个, 返回并删除class关键字, 然后在不向前声明capsule comp的情况下进行编译｡

109
00:09:56,160 --> 00:10:04,080
‫现在, 当我说编译时, 我的意思是你可以从Visual Studio代码编译, 只是一个常规的C++编译｡

110
00:10:04,110 --> 00:10:11,670
‫您已经学习了如何执行此操作, 或者您可以简单地保存和Visual Studio代码并启动实时编码｡

111
00:10:11,670 --> 00:10:17,280
‫这两种方法都可以, 一旦我们一起完成了这一步, 我将向您展示这两种方法的效果｡

112
00:10:17,280 --> 00:10:22,440
‫如果您使用实时编码, 当然您将在实时编码窗口中看到生成的输出, 而不是在Visual

113
00:10:22,440 --> 00:10:27,270
‫Studio代码中看到的输出｡

114
00:10:27,270 --> 00:10:34,260
‫剧透一下, 你会得到一个编译错误, 看看编译错误信息, 看看它告诉你什么｡

115
00:10:34,470 --> 00:10:38,070
‫这只是让我们熟悉一下我们产生的错误｡

116
00:10:38,070 --> 00:10:43,500
‫然后, 在这之后, 返回并前进, 使用class关键字声明capsule comp｡

117
00:10:43,620 --> 00:10:48,450
‫一旦你完成了, 再编译一次, 这次你应该会得到一个成功的编译｡

118
00:10:48,780 --> 00:10:51,060
‫暂停视频, 给予｡

119
00:10:53,520 --> 00:10:56,350
‫好吧, 让我们在这里对代码进行一些破坏｡

120
00:10:56,370 --> 00:10:58,320
‫我将删除class关键字｡

121
00:10:58,700 --> 00:11:03,540
‫好的, 我们已经尝试编译了, 这是终端的输出｡

122
00:11:03,570 --> 00:11:10,830
‫我们看到的第一件事是错误, 它给了我们一个错误代码, 它说胶囊comp不是基地兵的成员｡

123
00:11:10,860 --> 00:11:17,940
‫我们有一个注释, 说C声明了一个基本兵, 然后我们看到我们得到了其他错误作为这个结果｡

124
00:11:17,940 --> 00:11:23,390
‫因此, 学生在尝试编译时往往会感到困惑, 似乎有多个错误｡

125
00:11:23,400 --> 00:11:28,560
‫这表明一个错误可以传播一系列错误｡

126
00:11:28,560 --> 00:11:31,670
‫这并不意味着你必须去修复一大堆文件｡

127
00:11:31,680 --> 00:11:34,410
‫该错误可能在此处有一个单一的起源｡

128
00:11:34,410 --> 00:11:36,420
‫我们知道错误的根源是什么｡

129
00:11:36,420 --> 00:11:37,820
‫我们需要向前声明｡

130
00:11:37,830 --> 00:11:45,150
‫现在, 让我们看看如果使用实时编码而不是常规编译和Visual Studio代码会发生什么｡

131
00:11:45,150 --> 00:11:51,450
‫接下来, 我将单击该按钮启动实时编码, 然后立即以红色显示构建失败,

132
00:11:51,450 --> 00:11:54,270
‫我们在这里看到了相同的内容｡

133
00:11:54,270 --> 00:11:55,050
‫就在这里｡

134
00:11:55,050 --> 00:11:59,310
‫封壳组件不是基本兵注释的成员｡

135
00:11:59,340 --> 00:12:01,860
‫见《贱卒宣言》｡

136
00:12:01,860 --> 00:12:03,750
‫所以我们在这里看到了同样的事情｡

137
00:12:03,750 --> 00:12:08,490
‫所以不管是哪种情况, 我们都会看到这样的错误, 当我们忘记forward声明的时候｡

138
00:12:08,490 --> 00:12:17,340
‫所以现在我们知道了它的样子, 现在我们更了解这些神秘的编译错误消息, 也更少了恐惧｡

139
00:12:17,460 --> 00:12:24,990
‫所以我们要做的就是通过前向声明你的封装组件来修复这个错误, 然后我们可以尝试再次编译｡

140
00:12:24,990 --> 00:12:27,780
‫现在我们已经编译完成, 没有任何错误｡

141
00:12:27,870 --> 00:12:32,070
‫现在我们看到了当我们忘记正向声明一个变量时的情况｡

142
00:12:32,100 --> 00:12:35,250
‫以后遇到编译器错误时请记住这一点｡

143
00:12:35,760 --> 00:12:41,490
‫总之, 我们讨论了创建新指针时的前向声明,

144
00:12:41,490 --> 00:12:49,020
‫我们了解到, 应该只包含CP文件中使用的内容, 而在H文件中应尽可能少地包含｡

145
00:12:49,050 --> 00:12:55,020
‫我们知道, 只要我们正向声明, 就不需要头文件来声明一个新的指针,

146
00:12:55,020 --> 00:13:00,090
‫如果我们要构造一个特定类型的对象, 就需要头文件.

147
00:13:00,090 --> 00:13:05,850
‫我们确实需要头文件来访问成员, 比如函数和变量, 我们看到,

148
00:13:05,850 --> 00:13:09,780
‫我们确实需要头文件来继承, 从类继承｡

149
00:13:09,780 --> 00:13:11,460
‫我们需要那个头文件｡

150
00:13:11,580 --> 00:13:17,160
‫现在我们知道了如何正向声明一个类型, 我们有了指针capsule组件, 我们已经准备好实际构造一个capsule组件对象,

151
00:13:17,160 --> 00:13:21,840
‫我们将在下一个视频中进行｡

152
00:13:22,200 --> 00:13:23,040
‫我很快就会见到你的｡

