Pessoal, estamos chegando quase no final dessa apresentação,
mas ainda tem uma coisa bem peculiar pra gente discutir.
Até agora
os operadores que foram sobrecarregados nas nossas funções...
deixa eu até ir pra versão 9 já.
Eles foram operadores com um único parâmetro,
e, via de regra, operador com um único parâmetro
ele só é sobrecarregado dentro da classe.
Só que tem operadores que têm dois parâmetros.
É o caso do operador de fluxo.
Operador de fluxo ele vai ter o parâmetro ostream,
como o objeto cout, por exemplo.
E um segundo parâmetro
que pode ser uma série de coisas.
Dado que o operador de fluxo
ele é sobrecarregado pra utilizar uma série de tipos
caractere, ponteiro de caractere,
classe string preexistente em C++,
inteiro, float, double
e assim vai.
A hora que você escreve lá no seu código
algo assim, ó.
Pegar só esse pedacinho do código aqui, tá.
Aqui eu tô salientando
porque que o operador de fluxo
tem dois parâmetros.
Inclusive, o operador de fluxo
o operador que tem dois parâmetros, ele é um operador
que não pertence à classe.
Ele é um operador solto,
ou seja, ele é um... na verdade, ele é uma função
que não está dentro de classe
Ele é independente, ele, na prática, ele é procedimental.
Se você olhar aqui, muito embora, ele trabalhe e ele receba objetos
ele é procedimental em si.
Se você olhar aqui, tá.
Todo operador de fluxo
ele vai ter
como primeiro parâmetro um objeto do tipo ostream.
Por exemplo, cout;
Por exemplo cerr.
São objetos preexistentes da classe ostream.
Vai receber, né.
Se eu olhar aqui, por exemplo, tá.
cout, fluxo e esse vetorzinho de caractere, aqui, fixo aqui.
Variáveis, né, vars.
Na prática, o que eu tô fazendo, gente,
é algo mais ou menos assim, ó.
Eu tô chamando o operador...
se concentre só nesse código que eu tô salientando aqui, tá.
Operador de fluxo.
É isso que acontece, tá. A hora que eu faço isso aqui, ó.
Tá aqui, um código que eu tô
salientando aqui, ó.
Esse código que eu tô salientando aqui.
A hora que eu faço cout << "vars.",
o que eu tô fazendo, na verdade, é operator fluxo
que recebe como parâmetro o cout.
Tá ali ó.
Que é do tipo ostream.
Inclusive por referência escondida diga-se de passagem.
E um segundo parâmetro.
Por definição, o operador de fluxo é preparado pra trabalhar
com constante char,
preparado pra trabalhar com char normal,
com vetores de char, com string,
com inteiro, com float, tá.
Ele tem várias implementações de operator.
Professor, se tem várias implementações do operator
porque que eu consigo trabalhar assim com fluxo, então,
com um único cout eu venho aqui e consigo imprimir
aqui é um vetorzinho de caractere fixo,
uma string, depois imprime um inteiro,
depois um float e, ainda, um comando end line.
Como é que isso é possível?
Tudo bem que o cout é sobrecarregado pra
trabalhar com vários tipos.
Inclusive, a gente até tá querendo sobrecarregar ele
pra trabalhar com um tipo a mais que é o MinhaString
Por definição ele não trabalha com isso,
mas eu posso ir lá no meu código e sobrecarregar mais uma vez o operador
pra ter como primeiro parâmetro
um ostream, normalmente um cout,
e, internamente, aqui, eu tô chamando de saída, inclusive.
E agora também, ademais, a MinhaString.
Mas, enfim, como é que ele pode trabalhar com tantos
parâmetros distintos e ainda fazer esse tipo de encadeamento aqui?
É isso que eu vou explicar pra vocês nesse preciso momento.
Se você olhar aqui o que tá acontecendo, pessoal.
É que esse é um momento aqui, no código destacado, aqui, em preto,
A gente cout recebendo por fluxo o "vars.".
Mas isso é uma maneira bonitinha de falar
na prática, o que tá acontecendo é que eu tenho um operador aqui, fluxo, né.
Como primeiro parâmetro cout que, na prática, é a tela, tá.
Se você quiser colocar assim.
E esse vetor de caracteres ali, fixo.
Só que esse cara, aqui, esse operator
além de executar, gente.
Além de executar isso aqui,
ou seja, ir lá na tela e imprimir isso aqui.
O que ele faz, depois de executar,
é retornar o próprio cout que tá aqui, ó.
Se você olhar aqui, ó.
Ele tem de volta.
Ele tem um retorno,
inclusive, um retorno que também pode ser referência escondida, by the way.
Coisa que acontece aqui, ó. A título de exemplo.
Eu retorno o próprio cout.
O cout retornado
eu posso rodar o código em azul.
O que vai acontecer com o código em azul?
Ele vai rodar aqui, no primeiro parâmetro,
o cout que veio da função, aqui,
inicialmente, aqui, na cor preta.
E aí, ele vai rodar aqui no código em azul
o cout retornado, aqui, do operador de fluxo em preto
com o s1 aqui.
Esse cara vai fazer o que então?
O cout que for retornado ele vai imprimir o s1.
E vai retornar um cout, aqui, azul
que vai ser aproveitado pelo operator verde
que vai usar o cout azul
e mais o i1 de verde.
Depois da execução em verde aqui
ele vai retornar então um cout verde
que vai ser utilizado pelo operator lá, laranjado, né, por assim dizer
e o f2 laranjado.
E retorna um cout pra ser finalmente utilizado pelo operator vermelho
que usa o cout retornado laranjado e mais o end line.
Eu posso até mostrar isso assim, ó.
Aqui, ó.
Essa primeira execução retornou esse cout aqui em preto.
Aí, essa segunda execução aqui, em azul,
retorna um cout em azul
que é utilizado pela execução em verde,
que retorna um cout verde, por assim dizer, né,
sei lá, é um termo pedagógico,
que é utilizado pelo operator laranjado
que retorna o cout laranjado
que é utilizado pelo operator vermelho.
Então, é esse encadeamento que faz.
Por isso que a hora que eu vou sobrecarregar
o operator de fluxo
eu tenho que respeitar que o cara que tá vindo na esquerda
vai ser do tipo ostream.
Tô usando aqui os operadores de...
os parâmetros, perdão,
com nesse operador 1, passagem de parâmetro por referência
por motivos já explicados.
Aqui, eu tô chamando de saida, eu podia chamar de cout mesmo, aqui dentro, tá.
Não teria problema.
Por causa da questão de contexto
ele ia se encontrar.
Esse é o cout no âmbito dessa função.
Eu chamei até de saida é pra diferenciar um pouquinho.
Então, a hora que eu recebo o cout por parâmetro, internamente, ele vai ser chamado de saida.
E aí, eu vou permitir imprimir nessa sobrecarga, agora, a MinhaString.
Então, eu tô permitindo que o cout
que o operador de fluxo
continue trabalhando com cout
mais MinhaString.
E depois da execução, retorne ainda o cout ou o objeto de ostream
pra poder fazer aqueles encadeamentos que eu disse pra vocês.
Na prática,
eu também tenho que implementar esse cara
fora da classe.
Porque conforme eu já disse
o operador de fluxo ele tem duplo parâmetro,
ele tem dois parâmetros
e ele é uma função solta, ele não pertence a classe nenhuma.
Como ele não pertence a classe nenhuma, ele não pode estar dentro de MinhaString.
É por isso que eu implemento ele
através de uma função solta
que está no mesmo .h de MinhaString,
mas não está dentro da classe MinhaString.
Vocês podem também, se quiser,
implementar isso via função amiga,
chamada função friend.
Existe no C++ uma possibilidade
que é uma função ser amiga,
uma função que tem intimidade com relação a classe.
Quando você declara uma função amiga da classe
ela pode estar dentro da classe, muito embora ela seja uma função solta,
mas que tem intimidade com relação a classe acessando a parte privada.
Coisa que eu não gosto, porque eu acho que viola encapsulamento.
Mas existe a função friend aqui.
Na minha opção, aqui, de implementação,
não é uma função friend é uma função externa.
Não tem porque ela ser friend.
Ela só está no mesmo .h por causa da coesão.
Como ela vai trabalhar com MinhaString,
então é normal que ela fique no .h da classe.
Que aqui é o .h. MinhaString.h.
Tem a classe MinhaString.
e mais uma função solta, aqui,
que é esse operador de fluxo sobrecarregado pra trabalhar, justamente,
com objetos de MinhaString.
Aí, no respectivo .cpp
que é o MinhaString.cpp,
além de ter as implementações das operações de MinhaString,
tem também a sobrecarga de fluxo trabalhando com MinhaString.
O que que ele faz aqui?
Do objeto saida aqui,
internamente chamado de saida, que na prática vai ser o cout.
Ele vai receber lá s.getString.
E aqui o s.getString,
vai retornar vetor de caractere
Operador de fluxo já é sobrecarregado por definição pra trabalhar com
vetor de caractere.
Então, ele imprime aqui, tranquilamente.
Eu podia se quiser imprimir, aqui, o tamanho
imprimir outras coisas aqui, nesse âmbito, se eu achasse pertinente.
Aqui, eu tô achando que é pertinente imprimir só o âmago
do MinhaString que tá vindo por parâmetro.
Colocando em saida, e retornando o objeto saida
pra poder fazer os encadeamentos que eu já expliquei.
Tá ali, ó.
Possibilita o encadeamento.
Através do comentário, aqui, em azul.
Legal.
Esse tipo de sobrecarga permite, então,
eu fazer esse tipo de operação.
E aqui vai fazer cout s1 end line.
Vocês estão vendo que aqui ele vai chamar uma execução
vai ser com cout s1,
e aqui vai ser mais uma execução com cout e end line,
permitindo já o encadeamento.
Bom, pessoal,
e aqui, então, vocês tão vendo que é possível sobrecarregar o operador de fluxo
inclusive, pra esse tipo de classe que eu criei, aqui, cito MinhaString.
Com isso, a gente tá chegando quase no fim dessa exposição sobre
sobrecarga de operadores.
Espero que tenha sido elucidativo, tá.
Essa exposição permitiu a gente tratar vários assuntos, né.
Lembrar o que é sobrecarga de métodos,
que é diferente de sobrecarga de operadores
que foi o âmago dessa aula,
permitiu a gente lembrar vários detalhes sobre
passagem de parâmetros por valor, por referência,
via ponteiros, por referência escondida,
os impactos disso.
Permitiu a gente relembrar peculiaridades de vetores.
Permitiu a gente, também, trabalhar a questão de constância
e peculiaridades, também, de constância.
Ainda, com relação a sobrecarga de operador
não é todo operador que pode ser sobrecarregado, tá.
Aqui, a gente sobrecarregou o operador de recebe.
Duas vezes, inclusive, ó.
Pra esse cara aqui receber
vetor de caracteres ou outro igual a ele.
Sobrecarregamos o operador de fluxo
sobrecarregamos o operador de igualdade, tá.
Agora há operadores que não são sobrecarregáveis.
Por exemplo, o operador ternário.
Operador ternário é esse cara aqui, ó.
Deixa eu voltar aqui.
Aqui, eu não estou fazendo se S2A é igual a S2B,
eu faço isso senão eu faço aquilo.
Em vez de eu usar um if, eu tenho um operador que permite fazer uma espécie de if.
if else, inclusive.
Que é esse cara aqui.
Operador de interrogação, dois pontos.
Se isso for verdade,
então, eu faço isso,
senão eu faço aquilo.
Isso aqui é equivalente a um if else, gente.
Esse operadorzinho ternário aqui, tá.
Vocês já devem ter visto isso em linguagem C.
Bom, se não viram estão vendo agora, tá.
Eu não gosto muito desse tipo de código,
mas muita gente utiliza.
Então, tá aí já pra se relembrar
e pra saber que ele não é sobrecarregável.
Ao melhor do meu saber.
Agora, existem outros operadores que são sobrecarregáveis
que vocês podem estudar.
Inclusive, verificar se, de fato, eles são sobrecarregáveis ou não.
Operador, por exemplo, de diferente, de mais, de menos,
de colchetes, de fluxo de recebimento.
Seria interessante estudar esses caras.
Inclusive, o fluxo de recebimento, aqui, ele tem peculiaridades, tá.
Antes de implementar vão no livro dos Deitel
ou qualquer livro de C++, aí, correto
e estude as peculiaridades do operador de fluxo de entrada.
Tem, inclusive, nas provas que eu disponibilizei no meu site
que a gente usa o operador de entrada e eu mostro lá
como fazer com alguns nuances, lá, que eu explico na execução da prova.
Por fim, tem aqui, ó.
No projeto que desenvolvemos antes em sala,
o das universidade, utilize a classe MinhaString no lugar de char*.
Seria legal você ir lá e substituir os char* que tem lá, né,
por exemplo, na classe Pessoa,
tem lá o atributo nome.
Você pode ir lá e substituir nome,
em vez de ser um vetor de caracteres,
por um MinhaString
ou, se quiser, até por um string do C++.
E aqui eu deixo ainda uns itens pra estudar, né.
Espaço de nomes, classe aninhada,
classe pré-definida String, Grupo de Slides 13.
Avançar um pouco mais com os objetos constantes const
ou revisar, né.
E atributos e métodos estáticos, tá.
Todos esses itens vão ser vistos, aí, nos Grupos de Slides subsequentes, tá.
Agora, sempre é uma boa prática
o camarada estudar os slides de antemão, né.
Antes de ver as exposições, tá, e ver as aulas.
Bastante útil, porque isso aprimora
o nível de compreensão que ele vai ter do que tá sendo exposto.
Pessoal, eu espero que vocês tenham gostado dessa exposição, tá.
Só quero fazer uma pequena observação.
Deixa eu abrir aqui a minha página.
Antes, fechando isso aqui.
Aqui está ela.
Técnicas de Programação.
Nós estamos
aqui, ó.
Grupo de Slides do 1 ao 8.
A gente viu o 8.
Então, nesse âmbito que tem aqui,
os slides vistos.
A gente acabou de terminar o 8 que é esse aqui, tá.
Os códigos estão ali, inclusive, disponíveis pra vocês.
Aqui tem, no final, pra baixo,
4 exemplos de prova
que são provas que contemplam esses conteúdos dos slides do 1 ao 8.
Pode servir de exercícios pra vocês.
Vocês podem tentar fazer essas provas
e corrigir conosco
professores, com os monitores, enfim,
com os colegas e com a nossa revisão e assim vai.
Aqui também tem uma lista de exercícios, tá.
Nessa lista de exercícios
talvez tenha um conteúdo ou outro aí que não foi visto ainda,
daí vocês pulam esse exercício por ora.
Não é isso?
Ah, não. Perdão.
Aqui, na verdade,
é o que eu quero dizer que existem outras provas
disponíveis no site
que servem de exercício.
A maior parte dessas provas, aí sim,
tem conteúdos que não foram vistos ainda
então você não vai fazer prova,
dessas provas disponíveis,
conteúdos que, ou questões que tem
assuntos que não foram vistos
que vão ser objetos das exposições subsequentes.
Por exemplo, você não vai fazer uma questão da prova
que envolva polimorfismo,
porque a gente não viu polimorfismo ainda, tá.
Agora, se você quer fazer essas outras provas disponíveis,
então, antes dá uma estudada
no Grupo de Slides subsequentes
até o 16.
E, aí sim, você vai ter todo o conteúdo necessário pra fazer as questões
dessas provas, pelo menos, a parte de questões de código, tá. Bem entendido.
Aqui, tem um exemplo de ponto,
que permite você navegar com um ponto na tela,
o ponto como se fosse um personagem que você navega ele na tela usando as setinhas.
Isso é legal pra quem quer fazer jogo depois orientado
a objetos em C++.
E, aqui, tem exercícios, tá.
Inclusive, é um conjunto de exercícios voltado à interdisciplinaridade, né.
Voltados a temáticas de outras disciplinas.
Se, eventualmente, tiver algum enunciado
de assunto que você não viu ainda,
aguarde pra fazer o exercício,
ou vai lá e estude o assunto.
Como exceções, polimorfismo e por aí vai.
E aí, você volta a fazer o exercício.
Então, isso aqui é uma ponderação sobre essa página aqui
que traz o Grupo de Slide 1 ao Grupo de Slide 8, tá.
Nas próximas aulas a gente vai avançar aqui
pro Grupo de Slide 9,
depois pro 10, 11, chegando até o 16
e depois a gente avança subsequentemente, ainda, aqui pra baixo.
Bom, pessoal, é isso que eu tinha pra contar pra vocês
no dia de hoje.
Nos vemos brevemente na próxima exposição.
Bons estudos.