O que que mudou aqui?
No slide anterior, lá, no 13, 12, etc.
aqueles códigos poderiam tranquilamente, estar na main.
Como a gente tá trabalhando em C++,
você agora não usa mais a extensão .c, você usa a extensão .cpp.
Então, aqui, por exemplo, no main, vai ser main.cpp.
No main.cpp, eu tô colocando apenas a função main nesse momento.
Professor, mas como você consegue agora,
se na função main só tem isso aqui,
como é que você consegue criar o Einstein e o Newton?
Porque eu tô fazendo um #include "Pessoa.h".
Isso significa que no meu programa, no meu ambiente de desenvolvimento,
Eu tenho o... Um outro arquivo que é o Pessoa.h
O Pessoa.h está justamente na estrutura Pessoa.
Começa ali e termina aqui.
Toda pessoa tem esses quatro campos,
tem a construtora e tem a função Calc_Idade.
Tem também um include, que aqui já é um include externo, né,
que é o stdio, standard input output.
Com essa é uma biblioteca externa, feita por outrem,
você usa o operador de "<" e ">" aqui.
Então, a Pessoa.h inclui uma biblioteca externa,
já o main.cpp vai incluir o Pessoa.h que vai ser uma biblioteca nossa,
Daí, como é uma biblioteca nossa, a gente que fez, você usa aqui as aspas.
Percebam que aqui, eu tô melhorando a organização do programa,
eu tô deixando a coisa muito mais modular, tá, mais encapsulado.
Vejam que, se agora em um outro programa,
eu precisar de um módulo Pessoa que calcule a sua própria idade,
basta eu ir lá e incluir a Pessoa.h
de alguma base de .h's que tenha criado.
Claro que deveria de ter o lugar direcional ou o diretório, aqui, ou áreas onde está esse .h
mas o fato é que o .h já está criado.
Aqui eu faço uma observação, também, com relação a elemento público:
Um elemento público, ou public,
é acessível em qualquer parte do programa,
por exemplo, no main() ou em qualquer função.
De fato, olhe lá. Aqui eu estou usando idadeP,
idadeP de Einstein.
Por quê? idadeP é algo público.
Aqui eu tô usando o Calc_Idade() de Einstein.
Por quê? Calc_Idade() é público.
Em uma estrutura, struct, do C++,
todos os elementos são públicos, ou public, por definição.
Mas isso não impede de se explicitar usando a palavra public:
antecedendo os elementos.
Que é o que eu fiz aqui.
Muito bem.
Bom, seguindo essa linha de discussão de private e public,
nós temos aqui o slide 16.
Ali, gente, notem que agora os dados, ou os campos,
passam a ser private, ou privados.
private: vem aqui os elementos que são privados.
Depois, public: a partir daqui as coisas são públicas.
Vocês vejam que agora e isso,
num primeiro momento, pelo menos, a gente pode incluir como regra
as variáveis são privadas e as funções são públicas.
Aqui, então, eu tô criando o Einstein e o Newton que são do tipo pessoa.
Vejam que aqui eu tô usando a construtora e, tá ok, porque ela é pública, passando valores.
A construtora, o Calc_Idade e essa outra função que aparece aqui,
como elas fazem parte da classe, olha ali o ponto e vírgula,
elas também fazem parte da estrutura, perdão.
Olha ali o ponto e vírgula.
Elas têm acesso à parte privada da estrutura.
Quem não tem acesso à parte privada, é quem tá acessando a coisa de fora.
Aqui, o Einstein, por exemplo.
Função Calc_Idade do Einstein e a função construtora do Einstein,
tem acesso à parte privada do Einstein, a classe pertence ao Einstein.
Agora, de fora, eu só posso chamar o que é público.
Tanto é que tô chamando só a construtora aqui e o Calc_Idade()
e essa outra função aqui informaIdade() que eu já vou falar a respeito.
Bom, agora então, o Einstein
através da sua função pública Pessoa, vai receber esses valores,
que vai, internamente, alimentar os campos privados.
E tá ok, porque aqui a Pessoa tem acesso às suas coisas.
O Calc_Idade()? Calc_Idade() também vai receber ali a suposta data atual:
dia atual, mês atual e ano atual. Supostos, né.
ele vai fazer o cálculo e vai alterar o campo idadeP, conforme vocês já sabem.
Mas vejam que peculiar,
agora eu não posso vir aqui
e acessar mais os dados privados do objeto,
eu não posso vir aqui mais e fazer Einstein.idadeP.
Isso ia dar erro de compilação.
Tanto ia dar erro de compilação
que eu me obriguei a criar uma nova função pública
chamada informaIdade.
A única função... A única funcionalidade dessa função
é retornar o valor de idadeP.
Vejam que interessante,
informaIdade que pertence à estrutura pessoa,
ela tem acesso à idadeP.
Como informaIdade() é público eu consigo chamar informaIdade(),
que vai permitir, então, retornar o valor, aqui, no âmbito do printf
informando o valor calculado.
Nesse caso dado aqui, essa história de privado ou público permite o quê?
Permite que eu inicialize dia, mês e ano de Einstein, através da construtora.
Permite que eu faça o cálculo de idadeP em Einstein e que informe esse cálculo.
Agora, em nenhum momento eu consigo alterar idadeP,
a não ser através da função apropriada de Calc_Idade,
ou seja, isso tá me garantindo que eu respeite certos protocolos aqui.
Se eu tentar vir aqui a fórceps e colocar aqui
Einstein.idadeP = 1000; Eu não consigo.
Eu tenho que respeitar o protocolo de inicialização e depois o de cálculo de idade.
E, simplesmente, eu tenho acesso à informar a idade, mas não alterá-la
fora do contexto de Calc_Idade(), bem entendido.
Então, justamente, a ideia de privacidade
é você proteger os dados
de cada objeto, de cada módulo
pra quem vai utilizar de fora
respeite o rito de modificação de dados
que esse módulo tem.
Isso é natural se você olhar os objetos do mundo real, tá.
Você tem informação x que você não fica informando por aí.
Por exemplo, se alguém quiser saber meu CPF,
a pessoa vai ter que perguntar, e eu, conforme o contexto, vou informar ou não.
Se alguém telefona na minha casa lá,
com uma história equivocada pedindo meu CPF, eu não vou informar.
CPF é uma informação privada minha.
Eu que decido pra quem eu vou dar essa informação ou não.
Então, se inspirando um pouco nesse tipo de situação
Ainda que de maneira um pouco mais restrita
você tem aqui no C++ nas estruturas a ideia de privado e público.
Vocês sabem que lá no procedimental, você não usa variável global.
Você não usa variável global, porque se você usa uma variável global,
um procedimento muda aqui, outro procedimento muda ali,
outro procedimento, ainda, muda acolá e você não sabe o valor que tem.
Imagine que você chega em casa, com a sua carteira lá, com R$ 1000,00
e você põe essa carteira em cima da mesa.
A hora que você pôs a carteira em cima da mesa, a carteira virou uma variável global.
Você vai lá tomar seu banho e a hora que você volta
você acredita que na carteira tinha R$ 1000,00, a hora que você volta tem R$10,00.
Como a carteira virou uma variável global,
uma pessoa da família pegou R$100,00, outra da família R$ 10,00,
outro pegou R$ 500,00, outro pegou x, pegou y e quando você viu
você ficou com R$ 10,00, por quê? Porque a carteira virou uma variável global.
Esse é um exemplo bastante pedagógico,
pra você lembrar que variável global é ruim,
assim como variável pública em estrutura é ruim.
Então, via de regras, as variáveis das estruturas têm que ser privadas ou algo que o valha.
Muito bem. Ali até eu digo, ó...
Algo privado (private) em uma estrutura C++ (struct)
é acessível apenas no escopo dela.
Algo público (public)
em uma estrutura é acessível por qualquer elemento do programa,
por exemplo no main ou em outra
estrutura ou outra função, melhor dizendo.
Certo, agora vamos evoluir do slide 16 pro slide 17.
O que que mudou aqui?
Aqui, pessoal, eu vou parar de chamar a coisa de estrutura,
e vou usar um nome que é mais apropriado na orientação a objetos,
é a classe.
Observa no mundo real aí,
e você vê entes andando na rua,
você vê, por exemplo, lá, algo vindo.
Aí você vê que pela forma de se movimentar é uma pessoa,
porque você classifica os objetos que são similares como pessoas.
Então, você vê outro ente se aproximando
e você consegue chegar melhor você vê que ele se movimenta
através de rodas, você já vai intuir que é um carro.
Então, aqueles entes daquele tipo se classificam como carro.
A gente classifica os objetos.
Você vê um objeto voando, você classifica como avião
eventualmente se ele for um avião.
Isso considerado, na verdade...
Como a orientação a objetos ela se inspira no mundo real,
a gente usa o termo classe e não mais estrutura.
Então, Einstein e Newton são classificados usando a classe Pessoa.
Essa é a maneira mais correta de dizer.
Ainda que tem diferenças técnicas entre struct e classe, tá.
Na verdade, tanto struct quanto classe funcionam, compilam em C++ tranquilamente.
Bom, vamos fazer uma reflexão sobre isso.
No lugar de struct, em C++, é mais usual utilizar uma class.
Uma primeira diferença entre elas
é que em uma class os elementos são private por definição.
Ah tá, isso é importante , de fato.
Structs são public por definição.
Aqui se eu não colocar nada, eles são privados por definição,
porque a orientação a objetos protege a privacidade, conforme já discutido.
Uma class, classe, representa a estrutura geral de um conjunto de elementos.
Por exemplo a classe Pessoa diz que qualquer pessoa terá
uma idade, uma 'data' de nascimento e por aí vai.
Cada elemento criado a partir de uma class se constitui em um object,
um objeto, uma instância daquela classe.
Exemplos de classes ou instân... Perdão, exemplos de objetos,
ou instâncias, da classe Pessoa são, aqui no nosso caso dado justamente, Einstein e Newton.
Só pra colocar a coisa mais em termos da orientação a objetos, bem entendido.
Veja, que aqui mudou a palavra struct pra class
o resto não mudou nada.
Por quê? Porque eu tinha definido aqui o que era privado, o que era público,
Eu fiz as chamadas corretas lá, na minha estrutura.
Muito bem, aqui também tem alguns detalhezinhos
a serem considerados que é o seguinte:
em termos da orientação a objetos a gente não chama mais de campos ou variáveis da classe,
é mais correto chamar de atributos.
Então, as variáveis de uma classe são chamadas de atributos
que é uma maneira elegante de você utilizar o termo.
Já as funções, ainda que muita gente utilize,
eu mesmo as vezes por vício de linguagem vou dizer: "Ah, a função Calc_Idade da classe Pessoa".
o termo mais correto seria chamar de método.
O método Calc_Idade da Pessoa, ou a função membro da classe Pessoa.
Também, pessoal, parte da literatura vai usar o termo operação.
A operação Calc_Idade da classe Pessoa.
Isso só pra vocês terem um pouco mais de erudição com relação aos termos,
que a gente utiliza no tocante a uma classe.
Se tem classe vai ter atributos, aí vai ter métodos, função-membro, enfim.
Muito bem, aqui você tá percebendo que a classe Pessoa
tanto com seus atributos quanto com os seus métodos
tem como a implementação dos métodos
estão dentro da classe Pessoa.
Tudo definido num mesmo .h que seria aqui a Pessoa.h.
Todo esse código está dentro da Pessoa.h conforme a gente já discutiu.
Até tá mas não era interior, inclusive, Pessoa.h tá ali ó.
Legal.
Aqui tem reticências, tá.
Só por conta que... Pra ficar mais fácil a leitura
da gente aqui nesse momento, mas o código está ali ele só tá escondido, então ele tá aqui, tá,
é isso que as reticências indicam.
Agora imaginem na vida de vocês, que vocês têm uma classe que não tem três funções apenas,
tem, sei lá eu, 100 funções.
Mesmo com reticências,
essas implementações, aqui, dentro
diretamente aqui junto com... Na definição da classe,
elas podem atrapalhar um pouco a leitura da classe.
Por isso que, dentre outros motivos, tá, têm mais motivos que isso,
mas, do ponto de vista organizacional, eu posso separar
a definição da classe em dois arquivos.
Em vez de ter apenas o .h, como eu tenho aqui,
eu tenho uma alternativa que é fazer assim, ó:
.h e .cpp.
Então, no .h, esse exemplo dado, o Pessoa.h
eu tenho a definição da classe.
Classe começa aqui...
Classe Pessoa começa ali,
termina lá no ponto e vírgula.
Tem a parte privada, que são essas variáveis,
e tem a parte pública que tem aqui.
nesse momento agora, apenas a definição das funções.
Aí, aqui a título de exemplo o Calc_Idade(),
retorno void e eu tenho esse conjunto de parâmetros aqui, lá o ponto e vírgula.
Se tem um ponto e vírgula aqui, isso significa o seguinte:
que eu não estou mais implementando
a função junto com a sua definição, eu estou apenas definindo ela,
tal qual acontece com informaIdade() ou a construtora.
Isso significa que a implementação
dessas funções vão estar em algum outro lugar.
Que lugar é esse?
É o Pessoa.cpp.
No caso, dividir...
Em .h e .cpp a implementação de uma classe,
o .cpp vai ter a implementação das funções que foram definidas no respectivo .h.
Aqui, por exemplo, Pessoa.cpp
vai ter o código, o código tá escondido aqui, mas o código existe,
vai ter... Vai implementar o código de Calc_Idade() que tem esses parâmetros,
os três parâmetros, cujo retorno é void.
Calc_Idade() esse que pertence à classe Pessoa.
Esse operador de dois pontos aqui é pertencimento.
Aqui no Pessoa.cpp.
Eu tô imprimi... Eu tô também
implementando o informaIdade()
que pertence à classe Pessoa,
informaIdade() com retorno inteiro e conjunto de parâmetros vazio.
E tá aqui a implementação nesse slide demonstrada.
Muito bem.
Por que isso mesmo? Por que separar em .h e .cpp?
Pra deixar mais organizado.
É uma primeira justificativa, há outras.
Quando eu implemento... Deixo pra implementar as funções-membros, os métodos
no respectivo .cpp, no caso aqui Pessoa.cpp,
eu tenho que ir nesse .cpp e fazer um #include "Pessoa.h".
Quando Pessoa.cpp inclui Pessoa.h,
ou seja, quando 'algo'.cpp inclui 'algo'.h, significa que ele está implementando
as funções definidas naquele respectivo .h.
Aqui, ó, eles têm o mesmo nome, ta vendo, ó.
Pessoa.cpp... Aliás, pelo menos, o primeiro pré-nome aqui.
Pessoa.cpp está implementando Pessoa.h.
Bom, agora o main.cpp,
daí já é outro .cpp, é diferente do Pessoa.cpp é o main.cpp,
a hora que ele inclui o Pessoa.h
ele está incluindo o Pessoa.h e o seu respectivo Pessoa.cpp implicitamente.
Não preciso, aí, via de regra, não devo, incluir o .cpp, incluo só o .h.
Aqui eu vou ter o Einstein e o Newton do tipo Pessoa.
Passando valores aqui nos parâmetros, eu pego Calc_Idade do Einstein e Newton.
Calc_Idade() esse que recebe três parâmetros
que seria o dia, o mês e ano atual, conforme já sabido,
depois faço o cálculo de idade.
Bom, e aqui eu tenho o nosso primeiro programa orientado a objetos.
Agora se eu precisar, num outro programa que eu vier a fazer,
de pessoas que calculem as suas idades
basta eu ir lá e fazer um #include "Pessoa.h"
a partir do local que eu saiba onde está o Pessoa.h e o .cpp.
Tudo isso considerado, eu tenho um exercício pra vocês.
O exercício é o seguinte,
fazer com que a impressão, printf, da idade
ocorra dentro dos próprios objetos,
programando isto no método apropriado da classe Pessoa.
Aqui eu não gostaria mais que tivesse aí...
Tivesse que eu vir aqui e fizesse esse printf forçoso no main.
Eu gostaria que a partir do próprio objeto Einstein e a partir do próprio objeto Newton,
Essa impressão ocorresse.
Esse exercício que eu deixo pra vocês, nesse momento dado.
Bom, pessoal, então, eu deixo esse exercício para vocês fazerem com a devida calma,
antes de irem pra próxima... Próximo grupo de slides,
e o próximo vídeo...
que eu vier a fazer.