‫Então, nesta palestra, falaremos sobre o método virtual em C++.
‫Nós já vimos isso antes, nós o usamos, mas nós o entendemos completamente?
‫Deixe-nos ver.
‫Portanto, a ideia de um método virtual é que ele nos permite substituir funções em uma classe base.
‫Já vimos isso com coisas como começar, jogar e pegar o Unreal.
‫Mas vamos nos aprofundar nisso e entender por que eles são marcados como virtuais.
‫Ele nos permite alterar a funcionalidade dessa classe base e faz algo chamado Dynamic Dispatch, sobre o qual falaremos em um
‫segundo para entender o que isso realmente significa e por que os métodos virtuais não
‫são a funcionalidade padrão em C++ como são em muitas outras linguagens, como C Sharp.
‫Então vamos dar uma olhada nisso.
‫Vou fazer isso no site do CPP dot S-H para que não estejamos no Unreal aqui.
‫Estamos apenas analisando a funcionalidade bruta do C++ para que você possa entender esse recurso de linguagem e como
‫ele funciona.
‫Agora, a primeira coisa que vou fazer aqui é apenas ir em frente e limpar o método principal.
‫E em nosso caso de uso vamos pensar em uma classe para armas, visto que este é um caso de uso muito comum
‫para jogos.
‫Então, vamos dar uma olhada em uma classe, arrefecer a arma de forma bastante direta e, em seguida, teremos
‫o corpo desta classe como público e um método de disparo void.
‫E eu vou seguir em frente e declarar o corpo deste método de filmagem aqui na linha para manter as
‫coisas super simples.
‫By the way, você pode fazer isso se você não tiver visto isso antes.
‫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
‫mais rápidos e assim por diante.
‫Mas aqui, onde é apenas um exemplo de brinquedo, tudo bem.
‫Então vamos fazer um SD ver fora.
‫Então, usando C++ como material de string de saída e vamos explodir.
‫Basicamente, quando chamamos esse método e vamos para a linha final.
‫E esse é o corpo do nosso método de chute.
‫E podemos encerrar a classe onde a chave e o ponto e vírgula.
‫Então vamos em frente e realmente usar essa classe.
‫Vou criar uma variável my gun no main e vou chamar minha gun dot shoot e vamos ver se tudo
‫está funcionando aqui como deveria.
‫Aperte o botão de execução e estrondo.
‫Ele está chamando o método como esperávamos.
‫Agora, o que acontece se eu quiser estender minha arma e talvez fazer um rifle ou pistola que é chamado de pistola.
‫Então a pistola de classe é herdada da arma, que faria assim.
‫E se você não viu isso antes porque provavelmente não escreveu isso necessariamente antes, você
‫faz uma herança pública de armas para que outras classes possam ver que você herdou de arma.
‫E então fazemos na seção pública, queremos talvez criar nosso próprio método de disparo para a pistola que
‫substitui essa funcionalidade.
‫E em vez de imprimir bang no final, queremos imprimir pílula porque é uma arma menor, faz um som
‫menor e esse é o nosso método de disparo lá.
‫E vamos encerrar a aula aí.
‫E o que queremos fazer é criar uma pistola.
‫Então pistola minha pistola no método principal aqui.
‫E como eles estão apenas existindo aqui, bem no método main, não estamos usando ponteiros para eles.
‫É por isso que estamos usando o operador ponto aqui em vez da seta.
‫Então a minha pistola dispara.
‫Vamos ver o que isso faz.
‫Espero que imprima ppu, o que acontece.
‫Frio.
‫Ok, então vamos remover nossos métodos que estão chamando.
‫Atire diretamente neles e vamos ver como as coisas se comportariam com um ponteiro.
‫Então eu vou criar um ponteiro de arma chamado gun.
‫Peter.
‫E na próxima linha eu poderia fazer na mesma linha, mas para simplificar, vou fazer na próxima
‫linha.
‫Vou definir esse ponteiro de arma para apontar para o endereço do operador, o endereço
‫da variável minha arma.
‫E então porque é um ponteiro, precisamos usar o operador de seta para chamar o método shoot.
‫Então eu vou chamar de tiro na minha arma.
‫Vamos clicar em executar e obteremos o resultado como resultado.
‫Frio.
‫Agora o que acontece se eu fizer a mesma coisa?
‫Mas em vez de apontar a arma para apontar para a minha arma, coloquei-a para apontar para a minha pistola.
‫Vamos em frente e vamos correr agora.
‫OK.
‫Esse é um comportamento interessante lá.
‫O que está acontecendo aqui é chamar esse primeiro método em ambas as instâncias.
‫Então, por que esse segundo método de filmagem não foi chamado?
‫Temos uma pistola aqui como ponteiro.
‫Bem, o que acontece se você não tiver um método virtual é que, por padrão, o C++ usará o tipo do seu
‫ponteiro, que é um ponteiro de arma.
‫Lembre-se, ele usará esse tipo para encontrar o método a ser chamado.
‫Então, ele irá chamar esse método de disparo no topo, em vez do método substituído na pistola.
‫Para chamar o método substituído em pistol, ele teria que chamar.
‫Teria que ter um ponteiro do tipo pistola.
‫Agora tudo bem.
‫E você pode ver por que eles fazem isso.
‫É pela eficiência.
‫C++ tem tudo a ver com eficiência.
‫Se algo vai custar mais quando for compilado, quando for executado, o C++ não fará isso por padrão, a menos
‫que você peça.
‫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
‫de ponteiro de arma.
‫E é aí que entra o Dynamic Dispatch.
‫Esse termo chique basicamente significa que não queremos que ele faça isso.
‫O que queremos fazer é dizer, espere um segundo, o que está realmente armazenado naquele ponteiro de arma?
‫Qual é o tipo real lá?
‫E o tipo real que percebemos é que é um tipo de pistola.
‫E então temos que nos perguntar, existe um método para esse tipo que é substituído?
‫E sim, existe.
‫Então, como damos ao C++ a permissão para ser um pouco menos eficiente e nos dá a capacidade de
‫substituir sem ter que alterar esse tipo de ponteiro, o que nem sempre é necessariamente possível.
‫Na verdade, em muitos casos isso não é possível, como é o caso quando você tem sua própria classe ativa
‫personalizada.
‫O Unreal não tem o ponteiro configurado para apontar para sua classe específica, o que exigiria que eles mudassem todo o
‫mecanismo toda vez que você introduzisse uma nova classe.
‫Não, isso simplesmente não é possível.
‫Eles têm um ponteiro para algo do tipo act para estrelar.
‫Então, quando eles chamam begin play, você queria chamar seu método Begin Play.
‫Então tem que ser virtual.
‫E essa é a chave aqui.
‫Se ficarmos virtual na frente do método na classe pai, isso agora sinaliza para C++ que espera um segundo, se estou
‫chamando atirar em um ponteiro do tipo ponteiro de arma, preciso verificar se isso não é, por exemplo , uma
‫pistola e que este método de disparo foi substituído.
‫Então, se seguirmos em frente e corrermos agora, você pode ver que temos um estrondo e depois um pue.
‫Portanto, está funcionando como esperávamos com despacho dinâmico.
‫E esse é o termo para essa coisa em que basicamente queremos apenas verificar que tipo de tipo está realmente
‫sendo mantido no ponteiro e chamar o método relevante.
‫Agora, há um pouco mais de sintaxe que você nos verá usar com frequência, e essa é a
‫palavra-chave override.
‫E você coloca isso depois de um método que você está tentando substituir como virtual.
‫E basicamente a palavra-chave override não é estritamente necessária, nem é colocar virtual novamente contra algo na
‫classe filha de uma arma.
‫Então não precisa colocar virtual, mas não custa fazer isso.
‫Mas a substituição é particularmente útil porque nos permite apenas ter certeza de que temos nossa nomenclatura
‫correta.
‫Então, se eu clicar em executar, tudo será executado como antes quando eu substituir.
‫Mas digamos que eu erroneamente errei o nome desse método para não fazer a substituição.
‫E eu o chamei de atirador de notas, por exemplo.
‫Copiei o nome errado.
‫Digitei em vez de copiá-lo.
‫Se eu acertar correr agora, então você vê, nós temos o mesmo erro novamente porque estamos tentando esfriar para atirar.
‫Nós o substituimos por engano incorretamente.
‫Vai bang, bang.
‫Então, a maneira de evitar isso é dizendo: Bem, estou tentando substituir algo.
‫Então eu coloquei minha palavra-chave override aqui, e se eu tentar compilá-la agora, você pode ver que está dizendo que
‫o shooter está marcado como override, mas não há método, nenhum método virtual para eu substituir, nesse caso eu
‫posso ir , Ah sim, eu digitei errado isso.
‫Então, vou corrigir meu código e voltar para filmar.
‫E agora funciona como eu pretendia.
‫Portanto, é apenas um pouco de segurança extra, colocando essa substituição lá e instantaneamente isso.
‫Também nos protegeria contra o caso em que a coisa que estamos tentando substituir não seja virtual.
‫Se eu tentar fazer isso, você pode ver que está dizendo que está marcado como override, mas
‫não substitui porque essa classe pai não tem uma função virtual para atirar.
‫Espero que isso esteja dando a você uma visão geral de como C++ usa e implementa funções virtuais e por
‫que temos que ser tão explícitos sobre elas.
‫Agora, vamos pensar em mais alguns casos de uso para funções virtuais em geral.
‫Já vimos alguns do motor.
‫Onde você viu o virtual usado antes?
‫Onde você pode imaginar usá-lo?
‫Acabamos de ver um exemplo de caso de uso em que você pode ter uma arma e diferentes substituições que
‫implementam o disparo de maneiras diferentes.
‫De que outra forma você poderia imaginar o uso de funções virtuais para substituir a funcionalidade nas classes pai?
‫Quando você pensou em uma resposta para essas duas perguntas, vá e siga o link para
‫as discussões nesta palestra e poste sua resposta.
‫Veja os casos de uso e os lugares em que você os usou antes e veja o que outras pessoas criaram.
‫Talvez isso o ajude a solidificar sua compreensão dos métodos virtuais.
‫Isso é tudo para esta palestra.
‫Vejo você no próximo, onde usaremos métodos virtuais com raiva.