﻿1
00:00:04,440 --> 00:00:09,690
‫Então, nesta palestra, falaremos sobre o método virtual em C++.

2
00:00:09,690 --> 00:00:13,110
‫Nós já vimos isso antes, nós o usamos, mas nós o entendemos completamente?

3
00:00:13,110 --> 00:00:13,860
‫Deixe-nos ver.

4
00:00:14,220 --> 00:00:20,400
‫Portanto, a ideia de um método virtual é que ele nos permite substituir funções em uma classe base.

5
00:00:20,400 --> 00:00:24,690
‫Já vimos isso com coisas como começar, jogar e pegar o Unreal.

6
00:00:25,020 --> 00:00:29,640
‫Mas vamos nos aprofundar nisso e entender por que eles são marcados como virtuais.

7
00:00:30,030 --> 00:00:38,130
‫Ele nos permite alterar a funcionalidade dessa classe base e faz algo chamado Dynamic Dispatch, sobre o qual falaremos em um

8
00:00:38,430 --> 00:00:44,520
‫segundo para entender o que isso realmente significa e por que os métodos virtuais não

9
00:00:44,520 --> 00:00:50,610
‫são a funcionalidade padrão em C++ como são em muitas outras linguagens, como C Sharp.

10
00:00:50,910 --> 00:00:52,050
‫Então vamos dar uma olhada nisso.

11
00:00:52,500 --> 00:00:59,850
‫Vou fazer isso no site do CPP dot S-H para que não estejamos no Unreal aqui.

12
00:00:59,850 --> 00:01:05,130
‫Estamos apenas analisando a funcionalidade bruta do C++ para que você possa entender esse recurso de linguagem e como

13
00:01:05,130 --> 00:01:05,820
‫ele funciona.

14
00:01:06,300 --> 00:01:10,440
‫Agora, a primeira coisa que vou fazer aqui é apenas ir em frente e limpar o método principal.

15
00:01:10,770 --> 00:01:18,390
‫E em nosso caso de uso vamos pensar em uma classe para armas, visto que este é um caso de uso muito comum

16
00:01:18,390 --> 00:01:19,380
‫para jogos.

17
00:01:19,830 --> 00:01:26,700
‫Então, vamos dar uma olhada em uma classe, arrefecer a arma de forma bastante direta e, em seguida, teremos

18
00:01:26,700 --> 00:01:31,560
‫o corpo desta classe como público e um método de disparo void.

19
00:01:32,550 --> 00:01:38,400
‫E eu vou seguir em frente e declarar o corpo deste método de filmagem aqui na linha para manter as

20
00:01:38,400 --> 00:01:39,290
‫coisas super simples.

21
00:01:39,300 --> 00:01:41,310
‫By the way, você pode fazer isso se você não tiver visto isso antes.

22
00:01:41,520 --> 00:01:47,820
‫Mas, de um modo geral, queremos fazer as coisas em um arquivo C++ separado para manter as coisas separadas, para tornar os tempos de compilação

23
00:01:47,820 --> 00:01:49,560
‫mais rápidos e assim por diante.

24
00:01:49,860 --> 00:01:52,140
‫Mas aqui, onde é apenas um exemplo de brinquedo, tudo bem.

25
00:01:52,650 --> 00:01:55,260
‫Então vamos fazer um SD ver fora.

26
00:01:55,260 --> 00:01:59,730
‫Então, usando C++ como material de string de saída e vamos explodir.

27
00:02:00,360 --> 00:02:04,710
‫Basicamente, quando chamamos esse método e vamos para a linha final.

28
00:02:05,630 --> 00:02:07,820
‫E esse é o corpo do nosso método de chute.

29
00:02:07,820 --> 00:02:11,510
‫E podemos encerrar a classe onde a chave e o ponto e vírgula.

30
00:02:12,050 --> 00:02:14,680
‫Então vamos em frente e realmente usar essa classe.

31
00:02:14,690 --> 00:02:23,420
‫Vou criar uma variável my gun no main e vou chamar minha gun dot shoot e vamos ver se tudo

32
00:02:23,420 --> 00:02:25,670
‫está funcionando aqui como deveria.

33
00:02:26,000 --> 00:02:27,830
‫Aperte o botão de execução e estrondo.

34
00:02:28,210 --> 00:02:30,260
‫Ele está chamando o método como esperávamos.

35
00:02:31,040 --> 00:02:40,220
‫Agora, o que acontece se eu quiser estender minha arma e talvez fazer um rifle ou pistola que é chamado de pistola.

36
00:02:40,580 --> 00:02:46,970
‫Então a pistola de classe é herdada da arma, que faria assim.

37
00:02:47,180 --> 00:02:51,470
‫E se você não viu isso antes porque provavelmente não escreveu isso necessariamente antes, você

38
00:02:51,470 --> 00:02:56,090
‫faz uma herança pública de armas para que outras classes possam ver que você herdou de arma.

39
00:02:56,720 --> 00:03:04,220
‫E então fazemos na seção pública, queremos talvez criar nosso próprio método de disparo para a pistola que

40
00:03:04,220 --> 00:03:05,510
‫substitui essa funcionalidade.

41
00:03:05,510 --> 00:03:13,190
‫E em vez de imprimir bang no final, queremos imprimir pílula porque é uma arma menor, faz um som

42
00:03:13,190 --> 00:03:17,270
‫menor e esse é o nosso método de disparo lá.

43
00:03:17,450 --> 00:03:19,910
‫E vamos encerrar a aula aí.

44
00:03:20,510 --> 00:03:23,290
‫E o que queremos fazer é criar uma pistola.

45
00:03:23,300 --> 00:03:27,740
‫Então pistola minha pistola no método principal aqui.

46
00:03:28,640 --> 00:03:33,980
‫E como eles estão apenas existindo aqui, bem no método main, não estamos usando ponteiros para eles.

47
00:03:33,980 --> 00:03:38,240
‫É por isso que estamos usando o operador ponto aqui em vez da seta.

48
00:03:38,840 --> 00:03:42,020
‫Então a minha pistola dispara.

49
00:03:42,200 --> 00:03:43,190
‫Vamos ver o que isso faz.

50
00:03:43,670 --> 00:03:47,030
‫Espero que imprima ppu, o que acontece.

51
00:03:47,320 --> 00:03:47,690
‫Frio.

52
00:03:48,230 --> 00:03:51,470
‫Ok, então vamos remover nossos métodos que estão chamando.

53
00:03:51,470 --> 00:03:56,810
‫Atire diretamente neles e vamos ver como as coisas se comportariam com um ponteiro.

54
00:03:57,410 --> 00:04:01,580
‫Então eu vou criar um ponteiro de arma chamado gun.

55
00:04:02,640 --> 00:04:03,420
‫Peter.

56
00:04:04,600 --> 00:04:08,440
‫E na próxima linha eu poderia fazer na mesma linha, mas para simplificar, vou fazer na próxima

57
00:04:08,440 --> 00:04:08,860
‫linha.

58
00:04:08,860 --> 00:04:16,030
‫Vou definir esse ponteiro de arma para apontar para o endereço do operador, o endereço

59
00:04:16,030 --> 00:04:18,070
‫da variável minha arma.

60
00:04:18,670 --> 00:04:23,710
‫E então porque é um ponteiro, precisamos usar o operador de seta para chamar o método shoot.

61
00:04:23,830 --> 00:04:26,410
‫Então eu vou chamar de tiro na minha arma.

62
00:04:26,830 --> 00:04:30,310
‫Vamos clicar em executar e obteremos o resultado como resultado.

63
00:04:30,370 --> 00:04:30,850
‫Frio.

64
00:04:31,330 --> 00:04:34,420
‫Agora o que acontece se eu fizer a mesma coisa?

65
00:04:34,420 --> 00:04:40,570
‫Mas em vez de apontar a arma para apontar para a minha arma, coloquei-a para apontar para a minha pistola.

66
00:04:40,960 --> 00:04:42,280
‫Vamos em frente e vamos correr agora.

67
00:04:42,850 --> 00:04:43,200
‫OK.

68
00:04:43,210 --> 00:04:44,950
‫Esse é um comportamento interessante lá.

69
00:04:45,340 --> 00:04:51,610
‫O que está acontecendo aqui é chamar esse primeiro método em ambas as instâncias.

70
00:04:52,000 --> 00:04:55,450
‫Então, por que esse segundo método de filmagem não foi chamado?

71
00:04:55,450 --> 00:04:57,790
‫Temos uma pistola aqui como ponteiro.

72
00:04:58,390 --> 00:05:05,440
‫Bem, o que acontece se você não tiver um método virtual é que, por padrão, o C++ usará o tipo do seu

73
00:05:05,440 --> 00:05:07,900
‫ponteiro, que é um ponteiro de arma.

74
00:05:07,900 --> 00:05:11,820
‫Lembre-se, ele usará esse tipo para encontrar o método a ser chamado.

75
00:05:11,830 --> 00:05:17,920
‫Então, ele irá chamar esse método de disparo no topo, em vez do método substituído na pistola.

76
00:05:18,190 --> 00:05:22,780
‫Para chamar o método substituído em pistol, ele teria que chamar.

77
00:05:22,780 --> 00:05:25,390
‫Teria que ter um ponteiro do tipo pistola.

78
00:05:26,020 --> 00:05:27,490
‫Agora tudo bem.

79
00:05:27,490 --> 00:05:29,320
‫E você pode ver por que eles fazem isso.

80
00:05:29,320 --> 00:05:30,370
‫É pela eficiência.

81
00:05:30,370 --> 00:05:32,200
‫C++ tem tudo a ver com eficiência.

82
00:05:32,500 --> 00:05:39,220
‫Se algo vai custar mais quando for compilado, quando for executado, o C++ não fará isso por padrão, a menos

83
00:05:39,220 --> 00:05:40,420
‫que você peça.

84
00:05:40,750 --> 00:05:46,240
‫Portanto, é muito fácil para o C++ fazer a pesquisa e dizer: Bem, isso é um ponteiro de arma, então vou chamar esse método

85
00:05:46,240 --> 00:05:47,320
‫de ponteiro de arma.

86
00:05:47,740 --> 00:05:50,040
‫E é aí que entra o Dynamic Dispatch.

87
00:05:50,050 --> 00:05:53,890
‫Esse termo chique basicamente significa que não queremos que ele faça isso.

88
00:05:54,160 --> 00:05:59,910
‫O que queremos fazer é dizer, espere um segundo, o que está realmente armazenado naquele ponteiro de arma?

89
00:05:59,920 --> 00:06:01,960
‫Qual é o tipo real lá?

90
00:06:02,410 --> 00:06:06,040
‫E o tipo real que percebemos é que é um tipo de pistola.

91
00:06:06,310 --> 00:06:12,490
‫E então temos que nos perguntar, existe um método para esse tipo que é substituído?

92
00:06:12,490 --> 00:06:13,570
‫E sim, existe.

93
00:06:13,600 --> 00:06:20,080
‫Então, como damos ao C++ a permissão para ser um pouco menos eficiente e nos dá a capacidade de

94
00:06:20,290 --> 00:06:26,050
‫substituir sem ter que alterar esse tipo de ponteiro, o que nem sempre é necessariamente possível.

95
00:06:26,050 --> 00:06:31,660
‫Na verdade, em muitos casos isso não é possível, como é o caso quando você tem sua própria classe ativa

96
00:06:31,660 --> 00:06:32,170
‫personalizada.

97
00:06:32,650 --> 00:06:38,350
‫O Unreal não tem o ponteiro configurado para apontar para sua classe específica, o que exigiria que eles mudassem todo o

98
00:06:38,350 --> 00:06:41,110
‫mecanismo toda vez que você introduzisse uma nova classe.

99
00:06:41,350 --> 00:06:42,910
‫Não, isso simplesmente não é possível.

100
00:06:43,210 --> 00:06:46,210
‫Eles têm um ponteiro para algo do tipo act para estrelar.

101
00:06:46,450 --> 00:06:50,950
‫Então, quando eles chamam begin play, você queria chamar seu método Begin Play.

102
00:06:50,950 --> 00:06:52,450
‫Então tem que ser virtual.

103
00:06:52,690 --> 00:06:54,160
‫E essa é a chave aqui.

104
00:06:54,400 --> 00:07:02,440
‫Se ficarmos virtual na frente do método na classe pai, isso agora sinaliza para C++ que espera um segundo, se estou

105
00:07:02,440 --> 00:07:09,970
‫chamando atirar em um ponteiro do tipo ponteiro de arma, preciso verificar se isso não é, por exemplo , uma

106
00:07:10,150 --> 00:07:14,080
‫pistola e que este método de disparo foi substituído.

107
00:07:14,500 --> 00:07:19,180
‫Então, se seguirmos em frente e corrermos agora, você pode ver que temos um estrondo e depois um pue.

108
00:07:19,570 --> 00:07:23,800
‫Portanto, está funcionando como esperávamos com despacho dinâmico.

109
00:07:24,100 --> 00:07:30,340
‫E esse é o termo para essa coisa em que basicamente queremos apenas verificar que tipo de tipo está realmente

110
00:07:30,340 --> 00:07:33,160
‫sendo mantido no ponteiro e chamar o método relevante.

111
00:07:34,030 --> 00:07:39,670
‫Agora, há um pouco mais de sintaxe que você nos verá usar com frequência, e essa é a

112
00:07:39,670 --> 00:07:40,420
‫palavra-chave override.

113
00:07:40,420 --> 00:07:45,280
‫E você coloca isso depois de um método que você está tentando substituir como virtual.

114
00:07:45,910 --> 00:07:53,590
‫E basicamente a palavra-chave override não é estritamente necessária, nem é colocar virtual novamente contra algo na

115
00:07:53,590 --> 00:07:56,160
‫classe filha de uma arma.

116
00:07:56,170 --> 00:07:59,140
‫Então não precisa colocar virtual, mas não custa fazer isso.

117
00:07:59,650 --> 00:08:06,490
‫Mas a substituição é particularmente útil porque nos permite apenas ter certeza de que temos nossa nomenclatura

118
00:08:06,490 --> 00:08:07,000
‫correta.

119
00:08:07,000 --> 00:08:10,480
‫Então, se eu clicar em executar, tudo será executado como antes quando eu substituir.

120
00:08:10,810 --> 00:08:17,230
‫Mas digamos que eu erroneamente errei o nome desse método para não fazer a substituição.

121
00:08:17,230 --> 00:08:20,680
‫E eu o chamei de atirador de notas, por exemplo.

122
00:08:20,950 --> 00:08:22,720
‫Copiei o nome errado.

123
00:08:22,720 --> 00:08:24,280
‫Digitei em vez de copiá-lo.

124
00:08:24,610 --> 00:08:28,960
‫Se eu acertar correr agora, então você vê, nós temos o mesmo erro novamente porque estamos tentando esfriar para atirar.

125
00:08:29,320 --> 00:08:32,170
‫Nós o substituimos por engano incorretamente.

126
00:08:32,410 --> 00:08:33,550
‫Vai bang, bang.

127
00:08:34,060 --> 00:08:37,780
‫Então, a maneira de evitar isso é dizendo: Bem, estou tentando substituir algo.

128
00:08:37,780 --> 00:08:43,750
‫Então eu coloquei minha palavra-chave override aqui, e se eu tentar compilá-la agora, você pode ver que está dizendo que

129
00:08:43,750 --> 00:08:49,510
‫o shooter está marcado como override, mas não há método, nenhum método virtual para eu substituir, nesse caso eu

130
00:08:49,510 --> 00:08:52,360
‫posso ir , Ah sim, eu digitei errado isso.

131
00:08:52,360 --> 00:08:57,070
‫Então, vou corrigir meu código e voltar para filmar.

132
00:08:57,460 --> 00:08:59,290
‫E agora funciona como eu pretendia.

133
00:08:59,290 --> 00:09:04,130
‫Portanto, é apenas um pouco de segurança extra, colocando essa substituição lá e instantaneamente isso.

134
00:09:04,180 --> 00:09:09,130
‫Também nos protegeria contra o caso em que a coisa que estamos tentando substituir não seja virtual.

135
00:09:09,130 --> 00:09:14,620
‫Se eu tentar fazer isso, você pode ver que está dizendo que está marcado como override, mas

136
00:09:14,620 --> 00:09:19,210
‫não substitui porque essa classe pai não tem uma função virtual para atirar.

137
00:09:19,390 --> 00:09:25,540
‫Espero que isso esteja dando a você uma visão geral de como C++ usa e implementa funções virtuais e por

138
00:09:25,540 --> 00:09:28,090
‫que temos que ser tão explícitos sobre elas.

139
00:09:28,690 --> 00:09:32,860
‫Agora, vamos pensar em mais alguns casos de uso para funções virtuais em geral.

140
00:09:32,860 --> 00:09:34,690
‫Já vimos alguns do motor.

141
00:09:34,690 --> 00:09:37,360
‫Onde você viu o virtual usado antes?

142
00:09:38,510 --> 00:09:40,150
‫Onde você pode imaginar usá-lo?

143
00:09:40,160 --> 00:09:45,050
‫Acabamos de ver um exemplo de caso de uso em que você pode ter uma arma e diferentes substituições que

144
00:09:45,050 --> 00:09:46,640
‫implementam o disparo de maneiras diferentes.

145
00:09:47,390 --> 00:09:53,600
‫De que outra forma você poderia imaginar o uso de funções virtuais para substituir a funcionalidade nas classes pai?

146
00:09:53,600 --> 00:09:58,190
‫Quando você pensou em uma resposta para essas duas perguntas, vá e siga o link para

147
00:09:58,190 --> 00:10:00,890
‫as discussões nesta palestra e poste sua resposta.

148
00:10:00,890 --> 00:10:05,810
‫Veja os casos de uso e os lugares em que você os usou antes e veja o que outras pessoas criaram.

149
00:10:06,080 --> 00:10:11,150
‫Talvez isso o ajude a solidificar sua compreensão dos métodos virtuais.

150
00:10:11,240 --> 00:10:12,230
‫Isso é tudo para esta palestra.

151
00:10:12,230 --> 00:10:15,500
‫Vejo você no próximo, onde usaremos métodos virtuais com raiva.

