Pessoal, boa noite.
Aqui é o professor Simão falando.
Estou em Curitiba, no dia 5 de julho de 2020.
Hoje estou aqui pra falar pra vocês um pouquinho do
Grupo de Slides número 1,
mas agora da parte C, bem entendido.
Esse grupo de slides foi elaborado
pelo nosso monitor da disciplina
lá de Técnicas de Programação, que é o Vitor Corrêa.
Corrêa cursa Engenharia de Computação, colega de vocês.
Esse material ele trata sobre referências.
É um material curto
que traz um pouquinho mais de luz sobre o assunto de referências
que já foi tratado lá Grupo de Slides número 1, na parte B.
Seguindo aqui, vocês têm, então, o termo de referências.
Podemos dividir os tipos de variáveis simples
da linguagem C++ em três grandes grupos:
Variáveis normais, que guardam valores diretamente.
Ponteiros, que guardam os endereços
de outras variáveis, ou de outra variável,
e podem ser utilizados para obter o valor de onde apontam.
E, por fim, as referências que serão abordadas nesse grupo de slides.
Podemos imaginar, no tocante a referências,
cada referência é como um tipo de variável que age como um pseudônimo,
uma espécie de "segundo nome", para outra variável ou valor.
É bem por isso que, inclusive, o nome é referência,
porque permite depois, no final das contas, você fazer passagem de valor por referência.
Conforme será abordado no decorrer, aqui, dessa exposição.
Ali tem um exemplo bastante simplório, mas elucidativo.
Aonde você tem a definição de uma variável valor,
do tipo inteiro que recebe o valor 5.
Imagine que isso aqui tá na função main, tá.
Aqui eu crio, então, uma referência.
Pra eu criar uma referência, além de contar o tipo da coisa que vai ser referenciada
eu tenho que colocar esse "e comercial" (&).
Uma variável referência, na hora que ela é criada,
ela já tem que receber um valor.
No caso da passagem de parâmetro lá em função,
na hora que você chama a função você passa o valor
e é nesse momento que a referência vai ser criada naquele escopo.
Mas como a referência funciona?
Ela irá agir identicamente à variável que está referenciando,
como se fosse a própria variável.
Isso fica mais entendível no exemplo que segue.
Novamente, supomos que esse código aqui tá na função main.
Então, aqui você tem uma variável valor, inteira, que recebe 5.
Aqui, por sua vez, você tem uma referência, olha o & ali, inteira
que referencia, justamente, a variável valor.
Agora, se eu fizer valor receber 6,
e imprimir, em algum momento, o conteúdo da variável valor
vai imprimir 6, obviamente.
Agora eu faço ref receber 7.
Vejam que aqui na hora que eu imprimi o valor, que tá ali em cima,
valor vai imprimir o valor 7.
Por quê?
Porque eu alterei o...
o conteúdo da variável valor a partir da sua referência,
ref e valor, nesse caso, são exatamente a mesma coisa.
Olha aqui ó, ++ref.
Comando ++ ele permite fazer um incremento, né.
Nesse caso, eu vou tá incrementando
o que está referenciado em ref em 1,
se o que está referenciado em ref
é o conteúdo de valor, e valor está com 7, aqui ele vai passar pra 8.
Tanto é que, nesse próximo momento aqui,
eu vou imprimir o valor 8.
Outra coisa curiosa, se você imprimir
usando & na frente da variável valor
ele vai imprimir o endereço de memória da variável,
conforme tá ali exemplificado.
E se eu pôr um & na frente de ref,
também vai imprimir o valor de quem tá referenciado,
que é, justamente, o valor de memória da variável valor.
Diferentemente de um ponteiro,
uma referência deve ser... deve sempre conter um valor
que é atribuído em sua inicialização,
e que não pode ser mudado.
Então, de fato tá ali ó, aqui eu tenho uma variável de valor1
inicializada com 5.
E aqui a hora que eu crio o ref1
eu já tenho... o ref1 que é uma referência, bem entendido.
Eu já tenho que conectá-la a valor1.
Aqui, ó, nessa linha de código. Esse tipo de coisa aqui não funciona,
ref ela não recebe valor,
ref ela referencia
essa ref, que é uma referência, ela referencia uma variável normal.
Essa linha aqui, normal, sem dificuldades.
Uma variável valor2, inteira, que recebe 7.
Aqui eu tenho a criação de uma referência
chamada ref3 que recebe valor1.
Agora, vejam que interessante.
Se eu faço a ref 3 receber o valor2
O que vai acontecer?
valor1 vai ficar com valor 7 no final das contas.
Atribui o conteúdo de valor2, que é 7,
à variável referenciada por ref3,
ou seja, a variável valor1 passa a ter o conteúdo 7.
Muito bem, então esta aqui é a explicação do quadro geral de referências.
E quanto a sua utilização na prática?
Na prática, em C++, referências são utilizadas
quase que exclusivamente para facilitar a utilização de funções,
sejam como parâmetro ou como retorno.
Quando utilizada como tipo de parâmetro de uma função,
temos o que é conhecido como referência escondida,
quando utilizada como tipo de retorno é possível fazer um encadeamento de chamadas.
De fato essa informação é verdadeira.
Muito embora depois eu vá estruturar um pouquinho melhor esse...
presente slide aqui.
Vamos lá. Referência escondida.
O termo referência escondida se refere
a quando o tipo de um ou mais parâmetros de uma função
é do tipo referência,
assim, o parâmetro irá referenciar a variável passada à função e poderá modificá-la.
Na prática, a gente já viu exemplo disso, tá.
No Grupo de Slides 1 - Parte B.
Lá a hora que a gente trabalhava com a função Calc_Idade
ainda nas versões... procedimental,
na última versão procedimental, já em C++, bem entendido.
O C++ que permite trabalhar com o procedimental
e orientado a objetos, traz inovações, inclusive, no procedimental.
Uma inovação que ele traz no procedimental
é justamente permitir, de maneira procedimental, trabalhar com referências.
Coisa que acontece nesse exemplo aqui.
Olha lá, então, aqui tem um exemplo bastante pedagógico.
A função chamada altera número, retorno void,
tem dois parâmetros:
o num que é uma referência inteira;
e o novoNum que é apenas um inteiro.
E aqui dentro eu faço o num receber novoNum.
Na chamada de função
quem doar o valor aqui pra num
vai assim se alterar com o que acontecer aqui dentro,
pois é uma passagem de parâmetro por referência usando referência escondida do C++.
Aqui esse código, aqui, insisto, estria na main, né, na função principal.
Temos aqui uma variável numero, inteira, que recebe 5.
Lá eu chamo a função, passando a variável número,
que vai ser referenciada internamente na função,
e essa constante 3 aqui, ou esse valor constante 3, melhor dizendo.
O quê que vai acontecer aqui a hora que eu imprimir numero?
Como numero recebeu 3,
então numero vai ter o valor alterado aqui e vai imprimir 3.
Segunda chamada,
depois dessa segunda chamada, obviamente que numero aqui vai imprimir 7.
Só pra vocês lembrarem um pouquinho a dinâmica da passagem de parâmetro por referência escondida.
Referência escondida.
A utilização da referência escondida é extremamente útil
e bastante utilizada na prática,
porém deve-se atentar à chamada da função,
visto que a função pode modificar
a variável passada de parâmetro de maneira indesejada.
É, a gente discutiu isso na nossa aula anterior
que, de fato, você a hora que usa a referência escondida
pela chamada da função
você não tem o indicativo ali, explícito,
se a passagem está sendo por valor ou por referência,
você tem que olhar lá a definição da função, a assinatura da função,
pra saber se está sendo utilizado uma referência escondida ou não.
Devido à isso, é pertinente salientar a importância
da documentação de qualquer código escrito.
Ah, isso é verdade. Você pode lá na chamada da função,
se você conhece já a função, se você é o autor da função,
deixar uma indicação que é uma passagem de parâmetro por referência escondida.
Isso facilita a outros desenvolvedores que, eventualmente, vão dar, aí, manutenção no seu código.
Ainda, quanto ao encadeamento,
porque a referência escondida serve para fazer encadeamentos, tá,
em chamadas de função,
Esse assunto será visto no tópico sobrecarga de operadores.
De fato, a gente vê isso nos meus slides lá pra frente.
Bom, esse é um panorama geral
sobre referência escondidas, tá,
um material aí complementar, ao que já tinha sido ensinado para vocês.
Eu tenho uma confissão.
Eu, por reflexo, não uso muito referência escondida.
Eu acabo utilizando lá na sobrecarga de operadores, justamente,
que... naquele momento, naquele contexto
acaba fazendo um chamamento, né
pra utilizar esse tipo de estruturas, tá
de passagem de parâmetro.
Eu, por reflexo, utilizo ponteiros
para as minhas passagens de parâmetros por referência, via de regra.
Bom, um dos motivos pra fazer isso,
além de inércia cognitiva,
é questão de eu poder olhar a função, na chamada,
e já saber lá, né, que é uma passagem de referência
pelo fato de eu ter que passar o & lá na chamada, né,
já que é um ponteiro que eu tô utilizando.
Bom, tudo isso dito,
eu queria lembrar vocês que esses códigos, dessa parte C,
não estão disponíveis no site, porque são códigos extremamente simplórios.
Então, eu estimulo vocês
a pegarem um compilador, um Microsoft Visual C++
CodeBlocks, o Dev, o que vocês quiserem
e refazerem rapidamente esses códigos aqui
só pra pegar um pouco mais de fluência no tocante dessa questão estudada
Agora, entretanto, os códigos
da parte 1B, sim, estão disponíveis.
A gente já viu, na aula anterior, que se você for no meu site...
Vamos lá no meu site.
DAINF Jean Simão
Aqui está.
Meu site.
Aqui está a disciplina.
Então, aqui os slides que a gente tá estudando.
Ali, ó.
Parte... slides do Grupo de Slides número 1,
parte A, B e C.
A gente viu a C.
Na aula passada foi visto a B.
Os códigos da B também estão todos disponíveis se você clicar ali você baixa os códigos.
Eu já fiz isso, inclusive, falei sobre isso na aula passada.
Inclusive, eu tenho esses códigos aqui baixados, só um instantinho.
Voilà.
Estão ali então os códigos, os slides.
Do grupo de slides número 1, os códigos pertinentes.
Pessoal, conforme eu tava dizendo, na última apresentação,
esses códigos foram feitos com Visual Studio C++ 2013,
mas aí nesse período de pandemia eu tive
o desprazer de ter um HD queimado.
Aí eu tive que, no novo HD, reinstalar todo meu aparato
inclusive meu aparato de software, tá.
Tive que instalar o novo compilador da Microsoft
e aproveitei baixar o 2019.
A questão que como eu fiz os códigos em 2013
Se eu vier aqui, por exemplo, nessa versão aqui que eu chamei internamente de 1C,
e vim aqui e clicar direto no solution que no arquivo de projeto,
ele até abre,
ele até abre, mas a hora que eu compilar ele não funciona.
Então, o correto seria, vocês não abrirem por aqui,
mas sim abrirem o ambiente primeiro
e através do ambiente
lá do "Abrir Projeto" etc
abrirem o projeto a partir de lá.
e daí a hora que você faz isso, abre o projeto a partir do ambiente,
ele tem a decência de perguntar se você quer converter
2013 para 2019,
e se essa conversão não tem problema.
Mas vamos supor que, por engano, você vem e clica aqui.
Fiz inclusive, fiz isso, inclusive na versão aqui de baixo na 1D,
conforme falava pra vocês na aula passada.
vim aqui, me equivoquei, e cliquei ali.
Vamos cometer esse mesmo equívoco aqui, só que agora de maneira consciente.
Aqui no versão 1C interna aqui
vou por aqui no solution e vamos dar...
ProjetoOOExemplo, dar um duplo clique aqui.
Ele vai abrir o ambiente para mim.
Tá abrindo.
Pensando aqui um pouco.
Bom mostrar aqui a latência, mas foi.
Aqui ele tá dizendo
dando informações justamente sobre a incompatibilidade de versão.
Essa é uma informação, ele tá dizendo ó, você vai ter que fazer algo
Vou dar um Ok.
Abrir
Agora, se eu quiser,
diretamente compilar esse código que tá aqui,
que que eu posso fazer? Posso vir aqui e tentar.
Ir em Compilação e dar um Recompilar Solução.
Bom, e nesse caso ele foi.
Foi por quê?
Porque ele abriu aquela janela ali me dando ciência
que eu tava numa versão anterior
a hora que eu dei o Ok...
a hora que eu dei o Ok, ele foi lá e fez a conversão
que eu esperaria que acontecesse.
Acontece que, quando eu abri
essa versão aqui,
em vez de eu dar o Ok, naquela janela,
eu dei o Cancelar,
e a hora que eu dei o Cancelar
ele não fez a conversão e fica dando o erro que vocês viram na última aula.
inclusive a gente pode tentar fazer mais uma vez esse...
esse experimento agora só que usando uma outra versão
Só um instantinho, vamos ver se isso aqui executa.
Não deixa lastro.
Funcionou ali, ó.
Muito bem.
Deixa eu pegar uma versão qualquer de uma versão pra frente
pra tentar fazer esse experimento que eu tô tentando demonstrar pra vocês aqui.
Aqui, aqui tá falando
que foi feito em versão anterior
e tá dizendo que é possível atualizar pra versão mais recente
e eu vou dar uma Cancelar aqui
Supostamente, como eu dei Cancelar e não dei Ok,
ou seja, ignorei a mensagem,
as vezes numa ação reflexa, ou de maneira pensada,
aí eu vou abrir o projeto aqui
e vou tentar compilar, vamos ver o que acontece aqui.
Recompilar Solução.
Ó, e aqui ele dá o erro
que a gente tinha percebido na aula anterior,
porque
o ideal é sempre abrir pelo ambiente
que daí ele faz todas as correções necessárias
Clicando no solution
a gente tá percebendo que o ambiente, via do solution, a partir lá do Explorer,
ele abre, mas com suspeita, ele diz: "olha
dá a impressão que tem que converter isso aqui". Se der Ok ele converte.
Agora se der Cancelar, como eu fiz ali, ele não converte.
E aí como é que você faz, se você fez essa ação de maneira equivocada?
Pra reverter isso?
Bom, você vai aqui em Projeto, e você dá um Redirecionar Solução.
Se você não fez isso na abertura do projeto
de maneira equivocada apertando Cancelar, como eu acabei de fazer
você vem em Redirecionar Solução
e aqui ele vai fazer a mesma pergunta que ele fez na abertura.
Você dá um Ok,
e agora deu certo.
Se eu vier ali, ele vai permitir a recompilação.
Voilà, recompilado.
Aqui, posso iniciar a execução.
Ali tá perguntando, dia atual.
Hoje é dia 5 de julho de 2020.
Essa aqui já é uma versão lá pra frente que a gente vai estudar na sequência, tá.
Tô só executando aqui pra mostrar o ponto da conversão de códigos
de 2013 pra 2019.
Tá aí a execução funcionando bonitinho.
Bom, pessoal, essa aqui é uma aula mais curta.
Sempre que saírem de um projeto, fechem o projeto,
fechem o ambiente certinho
pra evitar qualquer tipo de
dano em arquivos.
terminamos essa exposição por aqui
e nos vemos, brevemente, na próxima
onde a gente já vai entrar no Grupo de Slides número 2.
Até breve.