Bom dia, pessoal, aqui é o professor Simão falando.
Hoje é dia 21 de agosto de 2020, 11h23 da manhã.
Fazendo 4°C nesse dia de hoje, em plena pandemia.
Bom, mas o que interessa é que estou aqui para falar sobre o grupo de slides 16,
onde a gente continua falando da standard template library, STL,
que é a biblioteca padrão de gabaritos,
já conhecida por vocês
que já foi tema de aulas anteriores, particularmente a última.
Hoje a gente fala, mais particularmente ainda, sobre vector e list,
agora para apontamento ou endereçamento de objetos.
Bom, tal qual na aula passada,
eu não coloquei o conteúdo em slides
porque agora eu quero que vocês vão direto para o código.
Acho que a gente já passou da fase de slides, podemos ir direto para o código.
Aí está, então, para vocês estudarem a versão 11 do sistema-exemplo,
o sistema das universidades,
observando o uso de string, list e iterator, vector e iterator,
vector com índice, ponteiro de vector com índice.
Claro, string é importante, mas já é um ponto batido, na verdade o fundamental é isso aqui,
é o que eu, realmente, quero que vocês se concentrem.
Depois tem um exercício
que vai ser subsequente à explicação que eu vou fazer no código, mas que é a seguinte:
Na versão 11 do sistema-exemplo,
o das universidades, aplicar os princípios de coesão e desacoplamento,
particularmente no tocante ao uso de
list e iterator, vector e iterator,
vector com índice, ponteiro de vector com índice.
Vocês vão ver que eu fiz uma solução com um nível de acoplamento,
justamente, a ideia é que vocês tirem o acoplamento,
para mexer com o código, desenvolver o código e simpatizar com ele,
tirando a solução desacoplante.
Eu vou explicar ali em termos de código que fica mais simples para vocês.
Eu vou fechar esse grupo de slides aqui.
Eu já deixei de antemão o código aberto.
Então eu tenho aqui a função Principal no meu, já conhecido, ProjetoOOExemplo.
Eu tenho o ObjetoPrincipal e eu tenho o Executar.
O que que tem dentro do meu Principal.h?
No Principal.h nós temos o usual,
só que agora vocês vão perceber o seguinte: aquelas listas
que em uma certa versão a gente tinha feito com um nível de acoplamento,
aqui o LUniversidades era uma lista parametrizada com Universidade,
depois vocês substituíram por uma lista desacoplada
chamada Lista, cuja a essência seria algo como isso que está sublinhado aqui,
essa lista parametrizada com Universidade.
Bom, nesse caso aqui dado,
eu substitui essa lista parametrizada por Universidade por uma list,
da STL, parametrizada por um ponteiro Universidade.
Ah professor, por que você já não fez uma lista desacoplada?
Porque eu quero que vocês façam, obviamente.
E também, aqui eu queria salientar alguns detalhes, prestem atenção.
Vocês vejam que aqui eu tenho o LUniversidades,
antes LUniversidades, dessa versão prévia que a gente já tinha feito,
ele era um list parametrizado com Universidade,
enquanto aqui o LUniversidade é um list
parametrizado com ponteiro de Universidade.
E por que essa diferença?
Por causa da essência dos templates.
O nosso template já foi programado, já foi projetado,
para hora que eu parametrize algo aqui, ele implicitamente vai trabalhar com ponteiro.
Já o list não, ele trabalha com o que vem,
se for Universidade, ele vai trabalhar com objeto Universidade dentro dele,
ele vai receber os objetos, vai copiar os objetos lá dentro.
Já aqui, se eu colocar ponteiro Universidade,
ele vai trabalhar com referências, no sentido de endereçamentos de Universidade,
que é o caso aqui.
Mesma coisa aqui, ponteiro Departamento,
então aqui eu coloco, na STL eu sou obrigado a colocar o asterisco na frente
por causa da maneira que foi composto o template.
Então, aqui eu criei um LUniversidades, LDepartamentos e LDisciplinas,
veja que esses caras aqui são todos lists.
Criei aqui um LAlunos e um LPessoas,
o LPessoas, a lista Pessoas, é um list parametrizado por ponteiro Pessoa,
já o LAlunos, só para diversificar, eu fiz um vector parametrizado por ponteiro de Aluno.
Aqui eu tenho iteradores para trabalhar com esses caras,
IteradorLUniversidades, IteradorLDepartamentos e por aí vai.
Em alguns momentos eu vou utilizar essas listas,
por exemplo, hora que eu for cadastrar um Aluno,
eu provavelmente estou utilizando minha lista LAlunos, que é um vector.
Vamos dar uma olhada nisso lá.
Então, está ali o CadAluno,
pergunta o nome do aluno, pergunta o RA que vocês já conhecem, cria o aluno.
O que está mudando agora?
É que eu estou usando não uma lista a partir do template que eu criei,
mas a partir de um template já existente, no caso o vector da STL.
Está aqui, então estou usando o push_back, já conhecido de vocês.
Bom.
Obviamente, se você for em outras partes do código,
por exemplo em CadUniversidades.
Vamos para a definição.
Então está aqui.
Ele vai usar o LUniversidades.push_back (univ) e colocar uma universidade que eu criei aqui em tempo de execução.
O que mudou, basicamente, do código que vocês já conheciam,
é que agora eu estou usando não mais as listas,
o template lista criado por nós, mas sim usando o template prévio existente no c++, no caso da STL,
particularmente os componentes vector e list, obviamente.
E assim vai.
Vamos ver o que é isso aqui, espiar definição.
Está aqui, eu posso espiar definição, olha que legal.
Então aqui é o CadDisciplinas,
não está feito, tem que fazer,
mas tem o do Departamento, em contrapartida.
Então aqui eu estou usando...
Ah sim, para cadastrar Departamento, eu tenho antes que saber a Universidade,
então eu busco lá Universidade, etc e tal,
e depois eu vou cadastrar o Departamento, daí tem lá o LDepartamente.push_back.
Bom.
Aqui, provavelmente, vocês vão ter no menu executar a utilização das listas.
Cadê? Ir para definição.
Está ali.
Listar Disciplinas, Listar Deparamentos, aquela coisa toda.
Está aqui, no caso 1 aqui.
Como eu não estou usando mais minha lista,
aqui com aqueles poréns e reticências que a gente tinha discutido em relação a isso,
mas aqui eu estou usando o iterador,
faço o iterador apontar para o início da LDisciplinas,
enquanto o iterador não estive no final da lista, vai ter iterador++.
A partir do iterador, que se comporta a lá ponteiro
pela sobrecarga do operador de apontamento, o asterisco aqui,
eu recupero a Disciplina que está lá dentro e informo o nome dela.
E assim vai para todos os demais elementos.
Está aqui o Departamento trabalhando com o iterador, com a Universidade,
inclusive com Alunos, porque o vector também, apesar do vector trabalhar com colchetes, ele também pode trabalhar com iterador.
Então está aqui.
Aqui também Pessoa, inclusive aqui...
aqui não é um quadro de polimorfismo ainda, porque isso é um getNome, getNome não é virtual.
Lá no ListeProventosPessoas eu provavelmente trabalhei com polimorfismo a partir
da lista main template da STL, que é o caso.
Aqui através do IteradorLPessoas ele chama o informaProventos
que daí cai em um quadro de polimorfismo porque o informaProventos é
é virtual, conforme já discutido anteriormente.
Aqui tem um problema grave,
tanto aqui quanto lá onde a gente estava,
porque a gente está com um código aqui de lista
imbricado, inserido,
misturadão dentro da classe Principal,
isso deveria estar desacoplado em outro lugar.
Bom, vocês já sabem a solução.
Você tem criar lá, por exemplo, uma classe ListaDisciplinas
aí o LDisciplinas que foi criado lá na Principal.h,
ele não vai ser do tipo lista, perdão, ele não vai ser do list
vai ser do tipo list parametrizado por ponteiro de Disciplina,
ele vai ser da classe ListaDisciplina, como está aqui,
só que a essência da classe ListaDisciplina
ela vai ser, no final das contas, tendo list como essência.
Daí, claro, você tem uma classe ListaDisciplinas, a essência dela
vai ser um list parametrizado por ponteiro de Disciplina.
O algoritmo de inserção dessa classe, basicamente, vai ser chamar o push_back da essência desse list,
e depois o algoritmo de percorrimento fica dentro do encapsulamento da classe conforme já discutido, conforme já sabido.
Bom, já que aqui não foi aplicada a solução desacoplada que vocês vão aplicar, bem entendido,
se vocês forem verificar outras classe, vocês percebem o acoplamento.
Pega qualquer classe aqui, vou pegar, sei lá eu, Disciplina.
Disciplina tem um vector aqui, Disciplina tem um vector de Aluno.
Se eu olhar aqui Disciplina, vai ter um listeAlunos.
Então vou fazer aqui, go to definition, ir para definição.
Ali de volta, listAlunos eu sou obrigado
a fazer o percorrimento com o uso do iterador.
O Iterador aponta para o início, enquanto o Iterador não aponta para o final, eu vou percorrendo a lista.
Inclusive aqui eu tenho uma outra versão, o listeAlunos2,
que faz o mesmo percorrimento, só que em vez de usar iterador, estou utilizando colchetes.
Tem tamanho lá que pega o tamanho da lista, do vector no caso,
ele converte isso para inteiro porque o size dá um long int e não um int, ele converte,
se eu não fizer essa conversão, ele faz automático,
mas é melhor garantir o óbvio em função de versões de compiladores.
Aqui é um for usual, "int i" recebe 0, enquanto "i" for maior que tamanho, "i++".
Aqui eu criei um ponteiro só para fins didáticos,
poderia fazer uma abordagem mais direta, mas em fim.
O "pa" é um ponteiro de Aluno que recebe nulo,
o "pa" vai receber o elemento que está dentro do vetor através do operador de colchetes,
e ai eu imprimo o nome.
Claro que eu poderia fazer uma abordagem muito mais direta, seria isso aqui,
também funcionaria sem obste,
mas eu fiz uma abordagem mais pedagógica.
Bom, qual que é a questão aqui?
Se você olhar esse exemplo como destaque,
você vê que eu tenho dentro do listeAlunos um código de percorrimento,
perdão, eu tenho dentro da Disciplina
uma função listeAlunos que tem um código de percorrimento.
Se eu olha lá o Principal,
eu tenho aqui outro código que também, como é no caso dos Alunos,
que também percorre os alunos, códigos muitos parecidos, quase idênticos, inclusive.
Se você tem códigos que são equivalentes, repetidos em duas partes do programa,
isso cheira mal, smell bad.
Significa que tem coisas aqui que não estão perfeitas, tem imperfeição.
Nos chama essa imperfeição.
Como que se resolve isso?
Insisto,
você vai criar lá uma classe ListaAlunos,
daí tanto aqui em disciplina, esse ObjAluno vai ser uma instância ListaAlunos,
quanto lá no Principal o objeto LAlunos vai ser uma instância ListaAlunos.
Daí a essência dessa classe ListaAlunos vai ser, obviamente, um vector parametrizado por ponteiro de Aluno.
Aí a função de inclusão dessa classe ListaAlunos vai ser simplesmente chamar o push_back desse cara,
e o percorrimento vai ser, o percorrimento que vocês façam,
seja através do iterador, seja através do operador de colchetes,
mas que vai ser utilizado em ambos os momentos,
tanto na Principal quanto na Disciplina, à luz de toda coesão e descoplamento.
Então aqui, na verdade, é mais para forçar vocês a utilizarem esses componentes e refazer esse código,
e também reforçar a reflexão sobre coesão e desacoplamento.
Se vocês forem olhar aqui, as outras classes também vão utilizar
listas que também tem quer ser desacopladas, inevitavelmente.
Beleza.
Professor, porque aqui você não está usando, criando um objeto de LDisciplinas, está criando um ponteiro da coisa?
Aqui porque já é velho conhecido de vocês, se vocês forem olha Disciplina,
pode ser porque já tinha incluído Departamento, Disciplina já tinha incluído Departamento.
Aí vocês sabem que Departamento não pode incluir Disciplina,
aí tem que usar aquele velho truque,
estratégia, estratagema,
de redefinir a classe aqui, usar ponteiro
para depois criar qualquer tipo de objeto,
e só nos respectivos .cpp que eu vou, realmente, fazer a inclusão pertinente,
está aqui inclusive,
e aí aqui que eu vou criar o que for de Disciplina, ou dependente de Disciplina, que é o caso do vector que é depende de ponteiro Disciplina.
Muito bem.
Claro, se eu fiz uma alocação de um objeto,
em função posta dessa estratagema de alocação de memória dinâmica,
depois eu tenho que fazer a respectiva desalocação.
Se eu tenho um new, eu tenho que ter um delete.
Pessoal, é isso que eu tinha para contar para vocês hoje.
Algo interessante, é que vocês que chegaram nesse grupo de slides 16 já estão preparados
para fazer todas as questões, praticamente todas as questões técnicas,
que vocês tem que escrever código efetivamente, das provas disponíveis lá no meu site.
Vamos lá no meu site um pouquinho.
Técnicas de programação.
Se a gente for percorrer aqui,
em algum lugar vai ter exemplos de prova.
Cadê?
Exemplo de Provas, está aqui.
Se você clicar em Exemplos de Provas, vocês vão ver que tem várias provas,
desde de 2008, são mais de 10 anos de provas,
por semestre, às vezes tinha 4 provas, então tem prova para...
porque teve várias turmas.
Então, tem prova para caramba aí.
Então, vocês podem fazer cada uma dessas provas aqui
como exercício.
Eu começaria pelas provas mais recentes, inclusive.
E é legal porque aqui você tem a prova,
você tem a prova, aqui, por exemplo, essa prova.
Está aqui o enunciado, enunciado bonitinho e tal,
e aí você tem ali, também, a solução, tanto a solução em código,
quanto a solução em diagrama quando foi solicitado.
Aqui, por exemplo, nessa prova só teve código e não teve diagrama,já na prova anterior teve código e diagrama.
Teve prova que eu dei diagrama e teve que fazer código,
teve prova que a gente já deu o código e o cara teve que resolver o diagrama,
teve prova que tinha que fazer os dois, daí claro,
tudo parametrizando em profundidade conforme o contexto
ou em complexidade conforme o contexto.
Se o cara teve que desenvolver código e diagrama,
supostamente, é uma complexidade,
se ele já recebe o diagrama, é outra complexidade e assim vai.
Tudo também depende do momento que aquela disciplina foi encarada, e assim vai.
Mas o fato é que você tem aqui, em todo fato de figura,
uma série de exemplos de provas
que lhe servem plenamente de exercício,
um exercício um pouco mais longo, obviamente, mas você pega esse enunciado.
depois de ter estudado tudo o que você estudou, pega esse enunciado,
põe o enunciado ali do lado e tenta desenvolver ele
com uma ferramenta de desenvolvimento ou mesmo no papel.
Coloca o enunciado na tela do computador
ou do teu celular, sei lá eu, e daí desenvolve
a prova no papel
porque no papel você vai ter que refletir a coisa,
não vai ficar fazendo tentativa e erro.
Faz uma simulação honesta, simula lá 2h de confecção
e vê o que você consegue fazer e depois vai comparar com as funções dadas,
ou discutir conosco, professores, ou com os monitores.
Bom, pessoal, então aqui a gente fechou os principais conceitos
mais aprofundados, vamos dizer assim, da orientação a objetos pura.
Depois para frente, a gente vai trabalhar com outros assuntos como, por exemplo,
cadê?
Como, por exemplo, programação visual,
a gente agora fez programação no console,
aqui a gente via fazer programação visual em janelas, botões,
e particularmente a gente vai tratar aqui a questão da orientação a eventos,
depois a gente vai permitir fazer programação com threads,
ou seja, com fluxo.
Hoje o programa de vocês tem um fluxo de execução só,
um program counter, um contador de programa só,
ou seja um fluxo de execução só,
mas é possível você ter fluxos concorrentes
através de threads.
Bom.
Aqui tem uma aula que não cabe mais em técnicas de programação,
é lá de fundamentos de programação 2,
mas aqui era um exemplo usando threads e TCP/IP,
ou seja, aqui eu permitia fazer um programa orientado a objetos distribuído,
ou seja, rodando em duas máquinas,
eles trocando objetos via protocolo de comunicação.
Bom, em todo o caso, todos esses caras aqui utilizam APIs,
application program interface,
para poder fazer esse malabarismo técnico expoente nessas aulas.
Depois a gente ainda vê padrões de projeto,
que afetam tanto a modelagem, o projeto, quanto o código.
Padrões de projeto são maneiras documentadas de vocês resolverem uma série de questões,
em programação orientada a objetos, sem ficar reinventando a roda.
Então esses daqui são os conteúdos que a gente vai ver nas aulas subsequentes.
Geralmente, esses conteúdos aqui, na disciplina de técnicas de programação,
a gente cobra muito mais em trabalho
do que em prova, muito embora tenha caído sim questões em provas,
mas as questões são ou de ordem teórica
ou se técnicas, a gente apresenta o código e discute o código a partir do código apresentado.
Então eu estou dizendo tudo porque se vocês forem fazer as provas de vocês, nas provas,
e se eventualmente na prova tiver alguma questão que envolva esses temas que vocês não viram aqui ainda,
e aí vão ser questões teóricas ou apresentando o código,
vocês podem ignorar isso aqui por hora,
mas podem fazer, obviamente, as demais questões
que vão pedir, essas questões vão pedir desenvolvimento efetivo de código
ou desenvolvimento efetivo de modelo.
Bom, isso só para dar uma orientação de como proceder com a realização dessas provas disponíveis para vocês.
É muito legal ter um banco de provas que permite o aluno, de maneira muito honesta,
entender o que vai ser cobrado dele no âmbito de uma prova, de um exame.
É interessante que vocês vão perceber que tem conceitos que sempre vão cair, é inevitável.
Vai cair a classe instanciação,
objetos, óbvio, vai cair associação,
vai cair agregação forte e fraca,
forte também chamada de composição, vai cair, via de regra, polimorfismo
às vezes cai estáticos, às vezes cai template,
então sempre tem ali os pontos que o aluno vai prestar atenção
que vai cair em prova.
Por que cai em prova? Porque é importante depois para a atuação profissional dele,
porque são recursos importante para a orientação a objetos.
Então as provas destacam esses recursos, justamente para a pessoa poder aprofundar
esse recurso e ter a formação nele, essa que é a ideia.
Bom, pessoal, nos vemos brevemente.
Espero que vocês tenham aproveitado a aula.
Bom estudo e se aqueçam porque está frio.