Alura > Cursos de Programação > Cursos de C e C++ > Conteúdos de C e C++ > Primeiras aulas do curso Orientação a Objetos com C++: Classes, métodos e atributos

Orientação a Objetos com C++: Classes, métodos e atributos

Conhecendo o projeto - Apresentação

E aí pessoal, sejam muito bem-vindos a Alura. Meu nome é Vinícius Dias e eu vou guiar vocês por esse treinamento onde nós vamos conhecer o mundo da programação orientada a objetos. E nesse treinamento nós vamos utilizar a linguagem de programação C++.

Assim como programação orientada a objetos é um paradigma muito completo e complexo, C++ também uma linguagem muito completa e complexa. Então durante o treinamento nós vamos ver detalhes bem interessantes de como o computador funciona, então isso é bem legal e eu particularmente gosto bastante, estou bastante empolgado para aprendermos isso juntos.

Então nós vamos desenvolver uma aplicação de um banco. Vamos começar a modelar uma conta e nós vamos entender o que uma conta tem, como trazer dados que existem no mundo real para o nosso sistema. Nós, a partir de uma conta, vamos ter também um titular, e de um titular nós vamos ter um CPF, e nós vamos ver como isso tudo se une.

Nós vamos aprender a juntar dados e comportamentos em uma única estrutura e vamos ver qual a vantagem disso. Nós vamos aprender a diferença entre classes e objetos, entre membros estáticos ou não estáticos, públicos e privados, vão ter várias palavras interessantes durante esse treinamento. E nós vamos, lá no final, ainda falar um pouco sobre otimização. Nós vamos falar sobre conversão implícita, vão ter muitos assuntos interessantes.

Então espero que você aproveite bastante. Caso alguma coisa não fique muito clara, você pode abrir uma dúvida no fórum, eu tento responder pessoalmente sempre que possível, mas quando eu não consigo a nossa equipe de alunos, moderadores e instrutores é muito solícita, então com certeza alguém vai conseguir te ajudar.

Agora chega de falação, e no próximo vídeo nós já começamos a colocar a mão na massa escrevendo o início do código que nós vamos trabalhar durante esse treinamento.

Conhecendo o projeto - Relembrando Structs

E aí pessoal, bem-vindos de volta. Então vamos entender o que nós vamos programar durante esse treinamento, precisamos fazer alguma coisa para entender os conceitos.

Nós vamos trabalhar como se estivéssemos criando um sistema de um banco, então nós vamos projetar algumas coisas como representar uma conta, realizar operações em uma conta, realizar saques, depósitos, etc. E precisamos fazer isso utilizando algumas boas práticas e nós já vamos entender como chegar nessas boas práticas. Então durante o desenvolvimento nós vamos entender o que é orientação objetos, o que esse nome tem a ver com desenvolvimento.

Mas vamos começar pelo começo, eu tenho uma base de um sistema, adicionei o using namespace std que nós já conversamos no curso anterior, o porquê de não adicionar esse em todo lugar. Mas vamos lá, o que eu quero fazer, eu quero representar uma conta. O que uma conta precisa?

Uma conta precisa do número da conta. Então eu vou armazenar na linha 8 string numeroConta = “12356”. Uma conta precisa ter o CPF do titular, na linha 9 eu vou armazenar, string cpfTitular = “123.456.789-10”. Precisa ter o nome do titular, para nós entrarmos em contato com ele, etc. E obviamente, toda conta precisa ter um saldo, eu vou colocar na linha minha conta com saldo de 100 reais.

Tenho aqui todas as informações necessárias para manipular uma conta. Consigo identificar o titular, consigo me comunicar com o titular através do nome, consigo identificar a conta em si pelo número, tem o saldo dela, tenho tudo que eu preciso.

Só que se eu precisar de uma outra conta, por exemplo, para realizar uma transferência entre uma conta e outra, eu vou precisar de todas essas definições separadas e eu vou ter que vir renomeando, usando nomes diferentes para as variáveis para não dar conflito. E isso não é profissional, nós não estamos fazendo isso da forma mais bem feita, vamos dizer assim.

Então o que nós podemos fazer, o que eu quero na prática é ao invés de utilizar string, float, int, bool, os tipos de dados que o C++ entrega para nós, eu quero criar um novo tipo. E o nome desse tipo vai ser conta e vai possuir todos esses dados mencionados anteriormente. Então o nosso tipo conta vai ter dentro dele um número, um CPF do titular, um nome do titular, um saldo. Então ele vai ter essas informações.

E muito do conhecimento que nós adquirimos nos treinamentos de C, vão servir para C++. C e C++ são linguagens completamente diferentes, mas a base, a parte mais simples é bastante parecida. Então como nós já vimos em C, em C++ nós também conseguimos criar algo que é chamado de struct. Então vamos criar uma struct.

Criar uma struct conta, e na prática o que eu estou dizendo, eu estou falando “olha só C++, eu quero criar um novo tipo. E esse tipo vai ser um aglomerado de outras variáveis, de outras informações”. Então eu posso trazer para cá, por exemplo, todos os dados aqui. Então eu vou copiar, vou colar, não preciso ter o Conta no nome da variável, é o número. E eu não vou ter o valor, porque é só definição e a cada conta que eu criar a partir desse tipo, vai definir os valores.

[03:28] Então o que eu estou fazendo, eu defini um novo tipo no meu sistema e o nome desse tipo é "Conta". Então a partir desse tipo eu posso criar variáveis, uma variável do tipo conta, por exemplo. Então, como eu crio um inteiro, int nomeINteiro. Para criar uma conta eu faço o tipo, que é Conta e o nome da variável, uma conta, por exemplo.

Lá em C, nós precisaríamos definir que isso é uma struct ou fazer um typedef. Mas em C++ isso não é necessário, eu simplesmente coloco o tipo e o nome da variável, umaConta.

Com isso, o que vai acontecer por baixo dos panos, o compilador vai pedir: “Olha só, eu preciso de um espaço de memória no meu stack frame”, que você já viu no treinamento anterior o que significa, e no stack frame dessa função, esse espaço de memória que eu preciso, precisa caber 3 strings e um saldo. Então esse é o espaço que eu vou precisar e é esse o espaço que vai ser reservado.

Então se eu tenho todo esse espaço reservado dentro dessa variável, então dentro dessa variável umaConta eu consigo acessar o cpfTitular, o numero, o saldo, e todas as informações.

Então ao invés de utilizar as variáveis separadas, eu vou utilizar umaConta.numero, umaConta.cpfTitular, umaConta.nomeTitular, e, obviamente, umaConta.saldo e eu vou definir como 100 reais.

Então, com isso, eu tenho toda a definição da conta em um local só, eu tenho um tipo específico para isso. E se eu quiser criar uma outra conta, eu não preciso ficar renomeando as variáveis, eu vou simplesmente criar umaOutraConta. E a partir dessa umaOutraConta eu posso acessar o saldo também, por exemplo.

E repara que eu tenho a variável umaConta modificando o saldo, e depois umaOutraConta modifica o saldo também. Então será que eu vou ter qual valor em umaConta? Eu vou ter o 100 que é original ou 200 que foi modificado? Vamos exibir e falar um pouco sobre isso. Então cout << “Uma conta: ” << umaConta.saldo << “ Outra conta: ” << umaOutraConta. Saldo << endl;.

Então o que nós esperamos que aconteça, que em umaConta.saldo eu tenha o valor de 100, e já em umaOutraConta.saldo eu tenha o valor de 200. Porque eu não quero que o valor de uma conta afete o valor da outra, os dados de umaConta são separados dos dados de umaOutraConta porque lembra, quando eu crio uma nova variável do tipo conta, eu estou separando um espaço de memória.

Então, em umaConta eu estou alterando o saldo desse espaço de memória e em umaOutraConta eu estou alterando o saldo desse espaço de memória, são espaços diferentes. Então quando eu fizer o build na parte superior da tela “Build > Run > Build and Execute” e executo esse programa, eu tenho exatamente o que eu esperava, uma conta tem 100 reais e uma outra conta tem 200 reais.

“Ah Vinícius, isso eu já sabia, eu já aprendi isso em C”, então essa revisão é importante por quê? Com isso, com esse conhecimento nós conseguimos começar a modelar os nossos dados, trazer algo no mundo real para código, fazer uma abstração de algo que existe, uma conta, por exemplo, para o nosso código contendo só as informações que nós precisamos.

Grava essa palavra “abstração”, nós vamos falar mais sobre ela ainda, mas basicamente foi que eu fiz aqui, pegar um conceito real e trazer de forma simplificada para o nosso sistema. E a partir desse dado, dessa variável especial, nós conseguimos acessar vários outros valores.

E em cima desses valores, eu quero realizar operações. Eu quero em cima de uma Conta, por exemplo, realizar saques, depósitos, transferências, etc. Então vamos fazer isso, mas no próximo vídeo.

Conhecendo o projeto - Definindo funções

E aí, pessoal. Bem-vindos de volta! Então vamos lá, eu quero realizar operações nas minhas contas, operação de saque, de depósito, etc. Por enquanto, para nós pegarmos alguns conceitos, eu vou manter tudo no mesmo arquivo, mas já nós começaremos a organizar isso tudo.

Vamos criar, na linha 14, uma função void sacar(Conta conta) que vai sacar de uma conta, nós vamos realizar o saque dessa conta, então o conta.saldo vai ser ele mesmo, o próprio valor, menos alguma coisa. Então eu preciso receber um float valorASacar. Então, valorASacar.

Então eu tenho a realização de saque, eu recebo uma conta, e dessa conta eu saco um valor. Posso fazer a mesma coisa com depositar, depositar, recebo uma Conta, vou ter o float valorADepositar, e ao invés de diminuir eu vou aumentar, eu vou somar o valorADepositar.

Só que eu posso adicionar algumas verificações, se fosse uma função de uma linha só nem faria muito sentido. Eu posso fazer algumas verificações como: Se o valor a sacar for menor que zero, então significa que a pessoa está tentando sacar um valor negativo, isso não faz sentido. Então eu posso retornar não deixar a função continua executando. Talvez até exibir alguma mensagem de erro, cout << “Não pode sacar valor negativo”. Nós poderíamos tratar isso de forma mais elegante, mas assim já está ok.

Tem uma verificação. Eu posso verificar também se eu estou tentando sacar mais do que eu tenho na conta. Então, por exemplo, se valorASacar for maior que conta.saldo, então não posso, cout << “Saldo insuficiente” << endl;. Então repara que nós podemos realizar várias verificações para isso que faz sentido ter uma função. Faltou o return.

Então vamos lá, deixa eu adicionar essa verificação no depositar também, se o valorADepositar for menor que zero, eu estou tentando depositar um valor negativo, não faz sentido também. Então ok, nós já temos as funções prontas para serem usadas e se eu vier aqui, eu tenho essa umaOutraConta, vamos trabalhar nela que ela está mais simples.

Se eu tentar depositar alguma coisa, depositar(umaOutraConta, 500), em uma outra conta 500 reais. Então no final, o meu saldo tem que exibir 700, 500 + 200 = 700. Então vamos ver o que que vai acontecer, quando eu clico em rodar, ele continua com 200 na conta.

E o que aconteceu? você provavelmente já sabe o que aconteceu. A minha função depositar, ela recebe uma conta. Então quando eu digo que ela está recebendo uma conta, o que acontece na prática, quando nós chegarmos nessa função, eu vou pegar a variável umaOutraConta, eu vou copiar todos os valores desse local nas stack frame e vou copiar para dentro da stack frame do meu depositar.

Então o que eu estou manipulando no saldo da conta é uma cópia da minha conta. E nós já vimos como resolver isso. Lá em C nós utilizaríamos, por exemplo, ponteiros, só que em C++ nós temos uma grande facilidade de poder utilizar referências. Então o que eu preciso receber aqui para modificar essa conta é uma referência.

Então nessa função, eu chamo a função e passo a variável. Minha função, ela vai receber uma referência para essa conta, logo ela vai alterar conta original, a conta que está na stack frame da minha função main mesmo. E agora se eu rodar, teoricamente, no terminal eu tenho os 700 reais na conta.

Então nós conseguimos realizar operações, até aqui não tem nenhum segredo, nós conseguimos, obviamente, fazer funções usando struct, nada novo. Só que o que acontece, eu quero começar a trazer, eu quero começar a apontar alguns problemas com que nós temos feito.

Primeiro, se eu estivesse separando isso em arquivos que façam sentido, talvez a minha conta estivesse em um arquivo e essas minhas funções estivessem outro, não estão relacionados. Outro problema muito grande, eu consigo vir em qualquer lugar do meu sistema e pegar umaConta e mudar o saldo. Ao invés de ter 100 reais agora eu tenho 1000 reais, simples assim.

Então o que eu quero é, por exemplo, ter minhas funções de depositar e de sacar juntas com minha conta. Eu quero que a conta forneça essas funcionalidades de alguma forma, eu quero que essas funcionalidades estejam dentro do struct mesmo, vamos pensar assim.

E outra coisa, é que eu não quero dar acesso ao saldo, por exemplo, não quero que a pessoa consiga modificar esses dados aqui. Então esses são alguns problemas que nós temos quando trabalhamos com a programação procedural. Nós temos os dados em um lugar, por exemplo, uma struct, várias variáveis, uma union, qualquer tipo de dados. E nós temos as funcionalidades separadas, as funcionalidades em outro local como uma função separada, uma função independente.

Isso pode ser um problema, por exemplo, eu preciso receber um parâmetro a mais, preciso lembrar de receber ele por referência, então eu preciso ter cuidado com algumas coisas, e o principal problema nesse cenário, usando a linguagem C++, quando nós usamos essa forma de programar, com as funções separadas dos dados, eu preciso liberar acesso a todos os nossos dados.

E isso é um grande problema, eu não quero liberar o acesso ao saldo da minha conta. Eu quero que a pessoa, obviamente, consiga consultar o saldo, mas não modificar como ela quiser. A única forma de modificar o saldo deveria ser através das funções que a própria conta deveria definir, como sacar, depositar.

Então nós vamos começar a trabalhar para resolver esses problemas e no próximo vídeo nós vamos ver como juntar os dados da minha struct com as funções que manipulam minha struct.

Sobre o curso Orientação a Objetos com C++: Classes, métodos e atributos

O curso Orientação a Objetos com C++: Classes, métodos e atributos possui 162 minutos de vídeos, em um total de 65 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