Alura > Cursos de Programação > Cursos de C e C++ > Conteúdos de C e C++ > Primeiras aulas do curso Avançando com C++: Enum, templates e mais recursos

Avançando com C++: Enum, templates e mais recursos

Enums - Apresentação

Olá, pessoal! Boas-vindas à Alura, eu sou o Vinícius Dias e vou guiar vocês nesse treinamento, onde nós vamos avançar nos nossos conhecimentos de C++.

Durante este treinamento, vamos aprender algumas coisas bem legais. Por exemplo: vamos começar com a necessidade de armazenar o dia do pagamento de um funcionário, que recebe toda semana.

Com isso nós vamos aprender a representar tipos que sejam limitados, mas que não precisam ter comportamentos, então que não faz sentido criar uma classe, por exemplo. Vamos aprender como realizar operações em cima de um objeto. Por exemplo: ao tentarmos realizar uma soma diretamente em uma conta, nós vamos fazer um depósito nela.

Ao tentarmos exibir diretamente uma conta, vamos ver o que pode acontecer por baixo dos panos para que o cout, por exemplo, saiba imprimir uma conta. Nós vamos aprender a fazer com que uma função externa da classe tenha acesso aos seus membros privados. Vamos aprender novos tipos que o C++ nos fornece e vamos finalmente entender o que é essa sintaxe aqui, de sinal de menor e maior.

Enfim, esse será um treinamento bastante proveitoso, onde poderemos avançar com alguns temas bem interessantes de C++. Se durante o treinamento você ficar com alguma dúvida, não hesite, você pode abrir uma dúvida no fórum. Eu tento responder pessoalmente sempre que possível, mas quando eu não consigo nós temos uma grande comunidade de alunas, moderadoras e instrutoras, que com certeza, poderão te ajudar.

Então, mais uma vez, desejo boas-vindas e espero vocês no próximo vídeo, para já começarmos a colocar a mão na massa!

Enums - Dia do pagamento

Olá, pessoal! Precisamos armazenar uma informação a mais aqui. Os nossos funcionários no banco recebem semanalmente e cada funcionário pode selecionar e escolher qual o dia da semana que ele quer receber.

Então vamos armazenar o dia da semana do pagamento aqui. A princípio eu vou manter ele privado, depois nós veremos se preciso por de alguma forma. Eu vou armazenar como um número inteiro, a princípio. Não é algo muito descritivo, mas é uma forma simples de armazenarmos, 0 é domingo, 1 é segunda e assim em diante.

Eu vou salvar como um short int, ou seja, um “inteiro curto”, para não ocupar tanto espaço: short int diaDaSemanaDePagamento, ou posso digitar somente short int diaDoPagamento para ficar um pouco mais curto. Em cima eu posso adicionar um comentário para especificar o que é: //0 = Domingo, 1 = segunda, etc..

Perfeito, assim nós temos um novo atributo. Esse novo tributo nós precisamos receber no construtor, então vamos adicionar em Funcionario(), antes de fechar o parêntese vou escrever (Cpf cpf, std::string nome, float salario, short int diaDoPamento);. Nós vamos no nosso construtor. Deixe-me ir à implementação.

O nosso construtor Funcionario::Funcionario eu vou receber também antes de fechar os parênteses: (Cpf cpf, std::string nome, float salario, short int diaDoPamento); e também vou inicializar dentro dele, após Pessoa(cpf,nome),salario(salario), diaDoPagamento(diaDoPagamento).

Perfeito! A princípio a nossa implementação está pronta, mas repare que isso não é muito intuitivo. Para a pessoa saber em qual parâmetro passará no Funcionario, precisará entrar na nossa classe, pelo menos na definição, e ler o comentário. Isso não é muito intuitivo. Vamos na nossa "main.cpp" e ver. Claro, nós temos vários tipos de funcionários.

Nós temos gerentes e caixa, eles precisarão nos passar esse dia do pagamento. Então vamos no "Gerente.hpp" primeiro. O gerente, antes da senha, vai receber o short int e vai ficar Gerente(Cpf cpf, std::string nome, float salario, short int diaDoPagamento, std::string senha).

Deixe-me fechar as outras abas abertas e trazer para cá uma implementação, que ele precisará passar no dia do pagamento: Funcionario(cpf, nome, salario, diaDoPagamento). , que será recebido pelo parâmetro short int diaDoPagamento.

Agora vamos no "Caixa.hpp", que também precisará receber o short int diaDoPagamento após o float salario,. Então, teoricamente, todas as implementações estão prontas. Deixe-me quebrar a linha. [02:51] Deixe-me fechar isso aqui tudo e abrir o nosso arquivo principal, que estamos chamando de "main.cpp". Aqui, na hora de criar um funcionário - eu estou criando algum?

Não estou criando nenhum funcionário! Então nós vamos criar aqui embaixo um gerente, Gerente, e o gerente será Gerente umGerente();. Ele tem os parâmetros aqui no construtor. O que o gerente precisa receber? Vamos na declaração do gerente - a minha ideia não está me ajudando. Mas sem problemas, vamos em "Gerente.hpp".

Ele precisa do CPF, o nome, o salário, o dia do pagamento e da senha. São bastante coisas! Eu preciso me lembrar, mas vamos continuar. Vamos lá! O CPF será Gerente umGerente(Cpf("000.000.000.-00"), "Nome do Gerente",. Eu estou sem criatividade para nomes hoje.

Como salário ele vai receber 1500, (em reais). O dia do pagamento que ele selecionou foi terça-feira, então domingo é 0, segunda é 1, terça é 2,. Repare que eu preciso pensar e entender o que eu estou fazendo aqui. Não está muito intuitivo, mas nós vamos continuar. A senha dele é super segura: , "123456");.

Temos aqui o nosso gerente. Vamos ver que erro está acontecendo, o que eu esqueci. Por isso que a minha ideia não estava me ajudando, eu não incluí o gerente aqui em cima: #include "Gerente.hpp".

Perfeito, agora está tudo dando certo! Repare que a forma como eu implementei funciona, ela é e uma forma simples e eficaz, é eficiente e ocupa pouca memória. É funcional, mas nós precisamos conhecer a implementação. Eu preciso ir à declaração de "Banco/Gerente.hpp" e ver. Aqui em “Banco/Gerente.hpp” não tem nada falando sobre dia do pagamento!

Eu tenho que ir em “Banco/Funcionario.hpp”, vamos à declaração de funcionário.

Aqui eu tenho um comentário informando o que é esse tal diaDoPagamento. Repare que não está nada intuitivo. Além disso, nada me impede de ir no meu código e passar 10 como dia do pagamento. Eu precisaria escrever manualmente algum tipo de validação desse inteiro.

Ou seja, basicamente, o que eu quero dizer é que eu preciso de um tipo, eu preciso criar um tipo para representar o dia da semana; porque usar um inteiro não faz nenhum sentido, não é prático para nós.

Além de não ser intuitivo na hora de escrever, eu precisaria criar regras de validação para garantir que o valor esteja correto. Eu posso passar um valor negativo aqui. Então, por enquanto esse código funciona, mas não está legal, está muito propenso às falhas.

No próximo vídeo vamos conhecer um recurso do C++ para resolvermos justamente esse problema!

Enums - Criando uma Enum

Olá, pessoal. Nós temos um problema, porque nós precisamos criar um tipo específico para representar o dia da semana para não permitirmos algo como 1500 ou até 17 e passarmos dias inválidos. Eu quero limitar os valores que eu posso passar aqui, e não passar um inteiro qualquer.

Provavelmente você já está pensando: “Vinícius, é moleza, nós criamos uma classe dia da semana e criamos uma classe domingo que estende o dia da semana, criamos uma classe segunda que estende o dia da semana e assim em diante”.

Porém, o que eu quero é armazenar esse valor e esse valor não terá nenhum tipo de comportamento intrínseco a ele. Ele não terá nenhum comportamento específico para cada um dos dias da semana.

Eu só quero ter esse valor armazenado para poder depois verificar o dia e pagar no dia certo. Então, basicamente, criar uma classe para cada dia da semana será o que chamamos de overkill, é usar uma bazuca para matar uma formiga, será muito trabalho para resolver um problema simples.

Tudo o que eu quero é limitar a quantidade de valores que eu posso passar aqui. Eu quero dizer: você só pode passar um inteiro que represente domingo, segunda, terça, quarta, quinta, sexta ou sábado; só. Para isso, nós temos os tipos enumerados ou, reduzindo, enum. Vamos criar uma enum para você ver como é.

Eu vou criar em um arquivo separado, eu vou criar um any file, que vou chamar de "DiaDaSemana.hpp". Vamos ver se ele vai criar corretamente. Eu tenho aqui um cabeçalho. Se é um cabeçalho, nós tendemos a usar o #pragma once para ele não ser incluído várias vezes na hora de compilar.

E eu vou definir uma enum: uma enumeração, um tipo enumerado, enum. Eu vou dar um nome para esse enum, igual fazemos com uma classe: enum DiaDaSemana {};. Aqui eu posso informar quais são os valores válidos para essa enum. Como eu já falei, os valores válidos são: Domingo, Segunda, Terca, Quarta, Quinta, Sexta, Sabado.

Esses são os valores válidos dentro de um enum. Aqui, o que por baixo dos panos o compilador vai fazer é como se ele estivesse criando algumas constantes: Domingo = 0, Segunda = 1, Terca = 2, Quarta = 3, Quinta = 4, Sexta = 5, Sabado = 6. Inclusive, essa sintaxe é válida. Se ao invés de começar no 0, eu quisesse começar do 1, eu poderia fazer Domingo =1 e ele iria incrementando.

Ele pensa que se o primeiro valor é 1, então o segundo é 2, o terceiro é 3 e assim por diante. Se eu quiser apenas valores pares, eu posso fazer isso tranquilamente informando os valores de todas as possíveis enumerações. Só que eu não quero, eu vou deixar o padrão mesmo porque, para mim, está ótimo o domingo começando no 0 e indo até o 6, que é sábado.

Dessa forma, eu tenho um novo tipo. Eu posso vir em "Banco/Funcionario.hpp", por exemplo, e ao invés de utilizar short int diaDoPagamento, eu vou utilizar DiaDaSemana diaDoPagamento. Só que é óbvio que eu preciso incluir esse cabeçalho lá em cima: #include "DiaDaSemana.hpp". Agora, ao invés de receber um short int em Banco/Funcionario.hpp, eu vou receber DiaDaSemana.

Aqui na implementação é a mesma coisa, ao invés de ser um short int será um DiaDaSemana. Repare como foi simples nós modificarmos de um inteiro para algo que tem significado. Mas se eu vier no "main.cpp", no Gerente umGerente eu estou passando um inteiro ainda. Se eu tentar rodar isso, vamos ver o que acontece.

Eu recebo um erro! Vamos ver que erro é esse, deixe-me expandir isso.

Vamos lá! O erro é conversão inválida de short int para o dia da semana. Então eu não posso passar um inteiro qualquer, ou um short int, em nenhum lugar. Mas vamos ver o que aconteceu aqui no "Banco/Caixa.cpp".

Eu ainda estou recebendo um short int. Vamos passar DiaDaSemana e #include "DiaDaSemana.hpp". Aqui no Caixa eu preciso receber um dia da semana, só que na definição também precisa ser dia da semana, então esse #include eu coloquei no lugar errado. Vou recortar ele.

Vamos colocar #include "DiaDaSemana" e no Caixa vamos por DiaDaSemana no lugar do short int. Vamos fazer a mesma coisa em "Banco/Gerente.hpp". Precisamos receber DiaDaSemana, vou incluir #include "DiaDaSemana" e na implementação ele vai receber DiaDaSemana.

Agora sim, não temos mais short int em nenhum lugar, acredito eu. Deixe-me fechar isso tudo, abrir o nosso "main.cpp", tentar executar e ver se acontece algum outro erro. Executei e opa, conversão inválida de inteiro para dia da semana.

Perfeito! Agora é algo mais próximo do que eu esperava porque eu estou passando em Gerente umGerente um inteiro. O que eu quero passar agora é uma variável do tipo DiaDaSemana. Vamos criar aqui um DiaDaSemana, que vai ser uma DiaDaSemana terca =.

Primeiro, antes de qualquer coisa, deixe-me fazer o #include "DiaDaSemana". Como eu informo o valor? Será que eu posso fazer DiaDaSemana terca = 2;? Porque terça era o 2. Vamos ver se isso funciona... Aparentemente eu tenho um erro.

Olhe só, não consigo transformar um dia da semana em inteiro. Então, ao invés disso, eu vou fazer DiaDaSemana terca = Terca;. Agora eu não tenho mais erro, eu posso passar uma variável DiaDaSemana. Repare que esta Terca é exatamente a terça dentro do "DiaDaSemana.hpp", essa Terca.

Então, na prática, se eu exibir esse valor - deixe-me fazer um cout<<terca<<endl;, isso vai exibir o valor 2 para nós. Quando eu rodar, quando eu executar esse código. Vamos abrir o terminal.

Eu tenho o valor 2 sendo exibido. Ou seja, por baixo dos panos, ele está armazenando um inteiro. Agora nós temos a praticidade de um inteiro, de eu não precisar ter comportamentos e criar várias classes, mas eu ter a especificidade de um tipo porque eu criei uma enum (uma enumeração).

Então aqui eu tenho a certeza de que eu não vou passar um valor inválido - como 12, por exemplo. A minha IDE já me avisa o sinal de erro.

Você não pode passar um inteiro aqui, nesse lugar que espera um dia da semana. Mas eu posso vir aqui e passar Terca, sem problema nenhum, não preciso criar uma nova variável para isso. Posso passar Domingo, sem problema. Posso passar uma Quarta e isso tudo vai funcionar sem problemas. No caso, esse gerente vai receber na terça-feira mesmo.

Assim, nós atingimos aquele primeiro resultado, mas tem um detalhe que talvez você esteja se perguntando: “Vinícius, antes eu podia especificar o espaço que ele ia ocupar, que era de um short int. Aqui ele está ocupando o espaço de um inteiro completo, então ele pode acabar ocupando espaço a mais”.

E se eu quiser especificar, olhe só essa enum DiaDaSemana, vai ser representada não como um inteiro, mas como um short int. Eu posso usar uma sintaxe igual a de herança, assim: enum DiaDaSemana : short int. Se eu quero garantir que os números positivos que serão armazenados, digito: unsigned short int. Se eu quero ocupar só um byte: unsigned char.

Talvez você tenha estudado, talvez você se lembre, que um char nada mais é, debaixo dos panos, do que um inteiro que representa alguma letra em uma tabela. Na prática, esse unsigned char só vai ocupar 1 byte de memória. Então, nós ocupamos espaço, mas continuamos utilizando um tipo que nos faça sentido.

Eu posso continuar utilizando esse Terca em Gerente umGerente, sem problema nenhum. Deixe-me executar e garantir que tudo continua funcionando e que nós não temos erro nenhum... Perfeito, o nosso terminal aqui está sem erro!

Agora já temos um tipo totalmente válido e que faz muito mais sentido, nós conseguimos limitar os valores que passamos. Mas tem um detalhe: se por algum motivo eu quisesse criar uma classe chamada Terca depois, eu não poderia, porque esse nome Terca já foi definido no escopo geral.

Se eu quisesse criar uma função chamada Domingo por algum motivo, não poderia, porque esse nome já está definido. Então eu quero limitar o escopo, por exemplo, com algo como DiaDaSemana::Terca, ou até Funcionario::Terca - que é algo que é específico do funcionário.

No próximo vídeo vamos entender como limitar o escopo de uma enumeração.

Sobre o curso Avançando com C++: Enum, templates e mais recursos

O curso Avançando com C++: Enum, templates e mais recursos possui 107 minutos de vídeos, em um total de 50 atividades. Gostou? Conheça nossos outros cursos de C e C++ em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda C e C++ acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri, a inteligência artificial da Alura

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas