Sobrecarga de operadores

Ver Todos os Exercícios

Teoria

E aí galera, aqui é o Juan do Responde Aí, e hoje eu vou falar de uma das coisas mais legais de orientação a objetos: a sobrecarga de operadores!

Imagina que pra sua aula de álgebra linear você fez uma classe chamada V e t o r que contém os atributos x e y e um construtor que recebe esses valores.

Agora você quer criar dois objetos o v e c A e o v e c B e quer somar estes dois vetores usando a soma vetorial:

v e c A + v e c B = x A + x B , y A + y B

Mas o que acontece se você utilizar a expressão v e c A + v e c B ? Você vai esbarrar em um erro! Pois o operador + não sabe o que fazer com a classe V e t o r .

Mas não se preocupe. Existe uma forma de ensinar os operadores a trabalhar com as classes que nós criamos: é a sobrecarga de operadores (em inglês, operators overload).

Uma breve revisão de operadores

Quando a gente viu operadores, nos concentramos naquilo que eles eram capazes de fazer, e nas regras de precedência e associatividade. Vimos que existem os operadores binários que trabalham com dois valores, e os operadores unários que trabalham com um valor.

Mas o que a gente não sabia na época é que operadores, a grosso modo, são um tipo especial de função. A diferença é que a gente pode escrever assim: 1 + 2 em vez de assim + ( 1 ,   2 ) .

Para um operador binário o primeiro parâmetro fica na esquerda e o segundo parâmetro na direita: a + b equivale a s o m a r ( a ,   b ) .

E para um operador unário o único parâmetro recebido é o da direita: ! a equivale a n e g a r ( a )

Sobrecarregando operadores binários

Você sobrecarrega um operador da mesma forma que sobrecarrega uma função. A diferença é que o “nome da função” é a palavra-chave o p e r a t o r seguido do símbolo do operador.

Por exemplo, vamos sobrecarregar o operador binário + para funcionar com a nossa classe V e t o r :

Na linha 12 nos iniciamos a sobrecarga avisando que o tipo da função retorna um vetor. Depois usamos a palavra chave o p e r a t o r e o símbolo + para informar que estamos sobrecarregando o operador de adição.

Na linha 13 criamos um novo objeto da classe Vetor para armazenar o resultado. Nas linhas 15 a 18 efetuamos as etapas da soma vetorial e retornamos o resultado.

Agora que temos um operador sobrecarregado, vamos colocar esse operador em prática:

Na linha 24 colocamos nosso operador sobrecarregado em prática e somamos os vetores v e c A e v e c B e guardamos o valor em v e c C . E pra garantir que deu tudo certo, na linha 26 e 27 imprimimos as componentes do vetor C.

Sobrecarregando operadores unários

Mas e se você quiser usar o operador de negativo - para inverter o valor do vetor? Este é um operador unário e só recebe um parâmetro. Vamos voltar no nosso exemplo e adicionar uma sobrecarga pro operador - .

Fazemos quase a mesma coisa que no exemplo anterior, porém como o operador é unário, passamos apenas um parâmetro para função. Agora vamos executar esse operador dentro da m a i n ( )

Na linha 33 aplicamos o operador de negativo no v e c C , e nas linhas 35 e 36 imprimimos as componentes de v e c C . E observando o resultado percebemos que deu tudo certo!

Com o que você viu até aqui, você já é capaz de responder quase todas as questões sobre sobrecarga de operadores! Porém, pra garantir aquele 10, vamos nos aprofundar mais.

Sobrecarga de operadores dentro da classe

Uma outra forma de sobrecarregar um operador, é fazendo isso dentro de uma classe. Nesse caso, o operador sobrecarregado será um método da classe. Fazendo dessa forma o seu código ficar mais organizado. Outra vantagem é ter acesso aos parâmetros privados da classe.

Uma diferença é que por padrão um dos parâmetros é a própria classe. Isso quer dizer que se o operador for binário a função recebe 1 parâmetro e se o operador for unário não recebe nenhum parâmetro.

Vamos refazer o exemplo anterior do operador binário + e do unário - , mas dessa vez vamos criar a sobrecarga como um método da classe.

Vamos escrever a nossa classe V e t o r :

Agora vamos sobrecarregar o operador +

Na linha 11 começamos o método de sobrecarga dizendo que vamos retornar um Vetor, depois usamos a palavra-chave o p e r a t o r seguida do símbolo + para indicar o operador que estamos sobrecarregando. O diferencial é que já está implícito que um dos parâmetros é a própria classe, então só precisamos declarar um parâmetro chamado v do tipo vetor.

Na linha 12 criamos uma variável auxiliar. Nas linhas 14 e 15 fazemos as contas. Note que podemos acessar os atributos x e y da classe diretamente, e somamos eles com os atributos do Vetor v.

Agora vamos sobrecarregar o operador unário - . A função dele é transformar valores positivos em negativos, e vice versa.

E fazemos um processo semelhante, na linha 29 começamos o método de sobrecarga dizendo que vamos retornar um V e t o r , usamos a palavra-chave o p e r a t o r seguida do símbolo - , porém como é um operador unário não precisamos adicionar nenhum parâmetro.

Agora vamos colocar nossos operadores em prática:

E podemos ver que deu tudo certo! A sobrecarga funciona direitinho.

Sobrecarga c o u t ( < < ) e c i n ( > > )

Uma das coisas mais legais que podemos fazer com a sobrecarga é modificar o comportamento do c o u t e do c i n pra facilitar a entrada e saída de dados.

Mas antes, você precisa saber que o c o u t é um objeto da classe o s t r e a m e o c i n é um objeto da classe i s t r e a m . Em poucas palavras, quando a gente chama o cabeçalho # i n c l u d e < i o s t r e a m > no início dos nossos programas, o que estamos fazendo é informando que queremos usar as classes i s t r e a m e o s t r e a m .

Um detalhe importante é que os operadores < < e > > só podem ser sobrecarregados FORA da classe. Ou seja, eles não podem ser sobrecarregados como membros da classe. Não podem ser métodos da classe!

Sobrecarga do < < e c o u t

Vamos considerar a mesma classe V e t o r que vimos até aqui:

Para sobrecarregar o operador < < e o objeto c o u t fazemos da seguinte forma:

Na linha 12 usamos a palavra-chave o p e r a t o r e o símbolo < < . A novidade está no uso do termo o s t r e a m & no começo da linha e do o s t r e a m   & S a i d a como primeiro parâmetro, que são necessários para que o método c o u t funcione corretamente! O segundo parâmetro da função é o Vetor v , que é o objeto que queremos imprimir no c o u t

Dentro da função, na linha 14, é só a gente usar o comando c o u t e escrever o que queremos imprimir normalmente.

E finalizamos na linha 15 retornando o parâmetro S a i d a . Novamente, é algo necessário para o c o u t funcionar da maneira correta.

Agora vamos testar a nossa sobrecarga:

Viu só?! Na linha 20 a gente só enfiou o v e c A no comando c o u t e a mensagem que queríamos imprimiu sem problemas.

Mas a grande vantagem é que podemos fazer mensagens mais complexas! Por exemplo, vamos modificar um pouco a sobrecarga do operador < < :

Fizemos uma mensagem bem complexa, que vai se comportar de maneira diferente de acordo com o valor da componente x . Veja como fica o resultado:

Sobrecarga do > > e c i n

O processo de sobrecarregar o operador > > e o objeto c i n é muito semelhante. Porém devemos usar a classe i s t r e a m .

Na linha 22 declaramos a função com a classe i s t r e a m a palavra-chave o p e r a t o r , o símbolo > > e com os parâmetros i s t r e a m   & E n t r a d a para garantir o funcionamento correto do objeto c i n , e com o Vetor v .

Importante: note que passamos o Vetor v por referencia usando o operador & . Isso é necessário para a gente poder inserir as informações do usuário diretamente no objeto de destino!

Agora vamos conferir o funcionamento da sobrecarga:

Detalhes da sobrecarga de operadores

Praticamente todos os operadores podem ser sobrecarregados, com algumas poucas exceções. Mas aqui está uma lista dos operadores que podem ser sobrecarregados:

Limitações

  • Não da pra mudar a ordem de precedência e associatividade dos operadores
  • Não dá pra criar operadores novos! Você só pode modificar os existentes.

Boas práticas

  • Sobrecarregue os operadores das suas classes sempre que fizer sentido.
  • Utilize os símbolos de maneira lógica. Por exemplo, não use o símbolo + para operações que que não tenham relação com soma. Não use o símbolo * para efetuar divisões, e etc.
  • Sempre que você sobrecarregar um operador, um dos parâmetros deve ser uma classe que você criou.
  • Use um operador sobrecarregado para sobrecarregar os outros operadores! Por exemplo, use a sobrecarga que você criou do operador + para sobrecarregar o operador + = . Isso garante a consistência das operações.

Erros comuns

  • Tentar alterar o comportamento padrão do C++. Por exemplo, tentar fazer a soma de dois inteiros se comportar diferente.
  • Sobrecarregar o operador + NÃO implica em sobrecarregar o operador + = . Se quiser, você precisa sobrecarregar os dois operadores!

Por hoje é só, pessoal!

Sei que foi bastante coisa então não esquece de dar uma conferida nos exercícios pra isso tudo ficar bem guardadinho aí! 😉

Sobrecarregando operadores binários

Sobrecarregando operadores unários

Sobrecarga de operadores dentro da classe

Sobrecarga c o u t ( < < ) e c i n ( > > )

Detalhes da sobrecarga de operadores

Exercícios Resolvidos

Exercício Resolvido #1

O que é sobrecarga de operadores? Como pode ser útil?

Passo 1

No C++ nós temos diversos operadores que ajudam a realizar diversas operações com os tipos primitivos da linguagem. Alguns operadores são binários (exemplo: + ) e recebem dois parâmetros, outros são unários (exemplo: & ) e recebem somente um parâmetro, e outros podem ter comportamento binário ou unário dependendo da quantidade de parâmetros (exemplo: - )

A sobrecarga de operadores é uma forma de adaptar estes operadores para funcionar com as classes customizadas que criamos. Basicamente, para executar uma sobrecarga de operadores tudo que precisamos fazer é escrever uma função utilizando a palavra-chave o p e r a t o r e o símbolo do operador como nome da função.

A sobrecarga é muito útil pois facilita o uso das classes e objetos, deixando a escrita e leitura do código mais simples, ajudando o programador a desenvolver classes melhores, principalmente quando as boas práticas são executadas.

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #2

Sobrecarregue os operadores de soma, subtração e multiplicação para o tipo P O N T O abaixo.

Passo 1

Vamos lá pessoal. Essa é uma questão de sobrecarga de operadores.

O exercício já nos deu uma classe e quer que a gente implemente as sobrecargas para os operadores binários + ,   - e *

Então, pra começar, vamos escrever a classe que a questão deu pra gente:

Passo 2

Vamos sobrecarregar cada um dos operadores, um de cada vez. Vamos começar com o operador de adição + .

Para sobrecarregar um operador é parecido com criar uma função, porém o nome da função é formado pela palavra chave o p e r a t o r e o símbolo do operador.

t i p o   o p e r a t o r + ( p a r a m e t r o s )

Para sobrecarregar o operador binário + precisaremos receber dois parâmetros do tipo P O N T O , e a função deve retornar um resultado do tipo P O N T O

P O N T O   o p e r a t o r + ( P O N T O   p 1 ,   P O N T O   p 2 )

No código teremos:

Em seguida fazemos o corpo da sobrecarga.

Primeiro precisamos de uma variável de apoio do tipo P O N T O chamada p 3 . Depois, somamos os componentes x e y dos pontos p 1 e p 2 , e guardamos os resultados nas componentes de p 3 . E por fim, usamos o comando r e t u r n para retornar o ponto p 3 .

Passo 3

O próximo operador é o binário, que vai receber dois pontos como parâmetros e efetuar uma subtração entre os pontos.

P O N T O   o p e r a t o r - ( P O N T O   p 1 ,   P O N T O   p 2 )

No código teremos:

O desenvolvimento do corpo da sobrecarga é muito similar ao anterior, precisamos de uma variável de apoio p 3 , onde vamos guardar o resultado da subtração dos componentes x e y de p 1 - p 2 . Usamos o comando r e t u r n para retornar o ponto p 3 .

Passo 4

O último operador é o * binário, que executa o produto dos componentes de dois pontos:

P O N T O   o p e r a t o r * ( P O N T O   p 1 ,   P O N T O   p 2 )

No código:

E vamos construir o corpo da operação mais uma vez. Criamos uma variável p 3 do tipo P O N T O , e nas componentes de p 3 guardamos o resultado do produto das componentes de p 1 e p 2 :

E isso finaliza a nossa classe e nossas sobrecargas.

Resposta

Exercício Resolvido #3

Sobrecarregue os operadores de inserção ( ≪ ) e de extração ( ≫ ) para realizar c o u t e c i n com tipo P O N T O abaixo.

Passo 1

Vamos lá pessoal. A questão pede pra gente sobrecarregar os operadores e .

Então, pra começar, vamos escrever a classe que a questão deu pra gente:

Olha que legal, a classe já possui um protótipo chamado I m p r i m e   , então podemos desenvolver esse método e depois a gente usa na hora de sobrecarregar o operador .

Passo 2

Vamos começar desenvolvendo o método I m p r i m e (   ) .

Este método é uma função-membro da nossa classe, então vamos usar o P O N T O ∷ antes do nome do método.

Essa função apenas vai imprimir os valores contidos nos componentes x e y da função.

Passo 3

Show, agora vamos pra parte principal da questão, a sobrecarga do operador

Lembre-se que o c o u t é um objeto da classe o s t r e a m , e teremos que levar isso em consideração na hora de sobrecarregar o nosso operador.

A forma padrão para sobrecarregar o operador para uma classe qualquer é a seguinte

o s t r e a m &   o p e r a t o r ≪ ( o s t r e a m   & S a i d a ,   P O N T O   p )

Já o corpo da sobrecarga é composto por uma sucessão de usos do c o u t . Porém, nós já fizemos o método I m p r i m e (   ) , então podemos só invocar este método

Um detalhe é que o parâmetro S a i d a pode ter qualquer nome, o importante é que seja retornado no final da sobrecarga.

Passo 4

O próximo passo é sobrecarregar o operador , mas não esqueça que o c i n é um objeto da classe i s t r e a m .

Então, para sobrecarregar o operador para a classe P O N T O devemos fazer assim:

i s t r e a m &   o p e r a t o r ≪ ( i s t r e a m   & E n t r a d a ,   P O N T O   & p )

Importante: não esqueça de passar o objeto p por referência usando o & . Passar por referência é necessário para poder alterar o objeto e inserir o valor no objeto.

No corpo da sobrecarga nós utilizamos o objeto c i n para inserir os valores digitados nos atributos adequados da classe.

O nome do parâmetro E n t r a d a também pode ser modificado, o importante é que esse parâmetro seja retornado no fim da sobrecarga.

Passo 5

A classe está construída e as sobrecargas estão feitas. Agora vamos testar!

Dentro da função m a i n (   ) vamos instanciar um objeto p n t da classe P O N T O

Como os operadores estão sobrecarregados, podemos pedir pro usuário inserir dois valores, e usar o c i n diretamente para armazenar os valores no objeto p n t , como fazemos na linha 32.

E como os operadores estão sobrecarregados também podemos usar o c o u t para imprimir diretamente o objeto p n t , como na linha 33.

O resultado é:

Resposta

Exercício Resolvido #4

Crie uma classe para os empregados de uma empresa. Eles devem ter os atributos privados n o m e e s a l a r i o , que devem ser inicializados no momento que o objeto é instanciado.

Sobrecarregue os operadores > e < para comparar o salário entre dois funcionários.

Passo 1

Vamos lá, galera.

A questão quer que a gente crie uma classe que represente os funcionários. Para inicializar o objeto no momento que é instanciado, vamos precisar criar um construtor.

Mas o ponto principal da questão é que ela pede que a gente sobrecarregue os operadores binários > e < para comparar o atributo salário.

Mas vamos começar com o cabeçalho: vamos inserir a classe < s t r i n g > para facilitar nossa vida.

Passo 2

Vamos construir a classe chamada E m p r e g a d o s .

Criamos os atributos privados: n o m e do tipo s t r i n g , e s a l a r i o do tipo f l o a t

Em seguida, vamos pro contexto público da nossa classe e vamos desenvolver o construtor. Criamos uma função sem tipo com o mesmo nome da classe ( E m p r e g a d o s ), e esta função receberá os parâmetros N o m e e S a l a r i o (linha 12).

No corpo do construtor, vamos guardar os parâmetros recebidos nos atributos da classe (linhas 13 e 14).

Passo 3

Seguindo em frente, é hora da sobrecarga!

O objetivo é sobrecarregar os operadores < e > para comparar com o atributo s a l a r i o , que é um atributo privado.

Para que os operadores tenham acesso ao atributo privado, o ideal é que eles sejam métodos da função! Então vamos sobrecarregar como função membro, para que a sobrecarga tenha acesso aos membros privados da classe.

Criamos a sobrecarga dentro da classe. A operação que queremos realizar deve retornar t r u e ou f a l s e , então o tipo da sobrecarga é b o o l . Em seguida usamos a palavra chave o p e r a t o r seguida do símbolo < .

O operador < é binário, e por isso utiliza dois parâmetros. Mas como estamos criando a sobrecarga como função-membro, o primeiro parâmetro, por definição, é um objeto da própria classe E m p r e g a d o s . Então só precisamos adicionar um único parâmetro, que será outro objeto da classe E m p r e g a d o s

b o o l   o p e r a t o r < ( E m p r e g a d o s   f u n c i o n a r i o )

Dentro do método de sobrecarga, vamos comparar o atributo s a l a r i o da classe com o atributo s a l a r i o do objeto f u n c i o n a r i o . O resultado dessa comparação é um valor booleano (1 ou 0), que vamos retornar.

Vamos efetuar o mesmo processo com o operador >

E isso finaliza a nossa classe!

Passo 4

Mas antes de fechar a questão, vamos testar a nossa classe.

Dentro da m a i n (   ) vamos instanciar dois objetos, eu criei dois funcionários com nomes e salários aleatorios

E vamos imprimir uma comparação entre esses dois empregados:

O resultado que obtemos é:

Resposta

Exercício Resolvido #5

Defina uma classe que representa um círculo com um método privado que calcula a distância entre os centros de dois círculos.

O círculo deve ser iniciado por no momento que for instanciado por um construtor que receba o raio e a posição x , y do centro.

Sobrecarregue o operador ^ para informar se há ou não intersecção entre dois círculos.

Teste usando o círculo c 1 de raio 1 e centro ( 0,0 ) e o círculo c 2 de raio 4   e centro ( 3 , 4 ) .

Passo 1

Beleza, pessoal. A questão quer que a gente desenvolva uma classe que instancie um círculo usando um construtor, e que use o operador ^ para verificar interseção entre dois círculos.

Para verificar se dois círculos se interceptam precisamos considerar a distância entre os centros d c 1 c 2 e os raios r 1 e r 2 das circunferências:

Mas vamos começar pelo cabeçalho!

Vamos incluir a < c m a t h > para facilitar as contas que vamos fazer.

Passo 2

Beleza, partimos agora pra criação da classe

Usamos o comando c l a s s e para desenvolver uma classe chamada C i r c u l o . No contexto privado dessa classe vamos declarar três atributos, R para o raio e X e Y para a posição do centro da circunferência:

Ainda dentro do contexto privado vamos desenvolver um método chamado d i s t a n c i a que calcula a distância entre este círculo e um segundo círculo.

Nós já temos acesso aos dados de um dos círculos, mas vamos precisar receber o segundo círculo como argumento da função.

Matematicamente, a distância entre o centro dos dois círculos é dada por:

c 1 c 2 - = x 1 - x 2 2 + y 1 - y 2 2  

Vamos implementar isso no nosso código. Criamos as variáveis auxiliares d e l t a _ X e d e l t a _ Y que armazenam a subtração dos atributos dos dois círculos.

Em seguida usamos as funções p o w e s q r t (contidas no cabeçalho < c m a t h > ) para calcular a distância, e armazenamos na variável auxiliar d i s t . O método é finalizado retornando o resultado de d i s t

Passo 3

Show de bola, agora vamos mudar nossa classe pro contexto público, e vamos desenvolver um construtor.

Não se esqueça que para fazer um construtor é só declarar um método sem tipo e com o mesmo nome da classe. 😉

Esse construtor irá receber três parâmetros r a i o , x e y , e usaremos esses argumentos para preencher os valores do objeto.

Passo 4

Agora vamos para a parte principal da questão. Vamos desenvolver uma sobrecarga no operador ^ para informar quando dois círculos possuem intersecção. Para isso o operador ^ é binário.

Note o seguinte, o exercício não pede a quantidade de interseções. Apenas quer saber se as interseções existem ou não, em outras palavras, se a existência de interseção é verdadeira ou falsa. Essa interpretação diz pra gente que o resultado de ^ é um valor booleano.

Outra coisa é que os valores que vamos trabalhar são o raio, e a posição x , y , que são atributos privados. Então vai ser mais fácil desenvolver a sobrecarga como função-membro da classe.

Então, mãos à obra: o método de sobrecarga é do tipo b o o l , usamos a palavra-chave o p e r a t o r e o símbolo ^ para indicar o operador que será sobrecarregado, e recebe um objeto da classe C i r c u l o como argumento.

Lembre-se que em sobrecargas como função-membro o primeiro argumento é a própria classe, e por isso só precisamos de um único argumento como parâmetro.

Agora vamos desenvolver o corpo do método de sobrecarga. A questão só quer saber da existência de intersecções, então basta a gente usar um i f - e l s e para testar os seguintes dois casos:

Vamos testar os dois casos em que não existe interseção. Caso nenhum deles seja verdadeiro, então a interseção existe.

S E   d i s t   >   r m a i o r +   r m e n o r   E N T A O   n ã o   e x i s t e   i n t e r s e c ç ã o S E   r m a i o r >   d i s t   +   r m e n o r   E N T A O   n ã o   e x i s t e   i n t e r s e c ç ã o S E   N A O   e n t ã o   e x i s t e   i n t e r s e c ç ã o

Mas antes vamos precisar definir qual é o maior e o menor raio. Pra isso usamos as funções m a x ⁡ ( ) e m i n ⁡ ( ) presentes na < c m a t h > . E usando o método d i s t a n c i a calculamos a distância entre os centros das circunferências.

E isso finaliza a sobrecarga da classe, e podemos finalizar a classe.

Passo 5

Agora só nos resta testar, pra ver se deu tudo certo.

Vamos criar dois objetos do tipo C i r c u l o , com os valores determinados no enunciado da questão: c 1 de raio 1 e centro ( 0,0 ) e o c 2 de raio 4   e centro ( 3,4 ) .

E agora vamos utilizar a operação c 1 ^ c 2 . Usando o c o u t podemos imprimir uma mensagem e o resultado.

E o resultado é:

Pra não ficar nenhuma dúvida, eu plotei essas circunferências numa calculadora gráfica e temos o seguinte:

O que mostra que nosso programa está funcionando.

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #6

Crie uma classe que represente uma pessoa, e sobrecarregue o c o u t ≪ para que as informações de um objeto da classe sejam impressas.

Passo 1

E aí, beleza?

A questão pede pra gente desenvolver uma classe com um c o u t ≪ sobrecarregado. Esse operador é baseado na classe padrão o s t r e a m , e por isso a sobrecarga dele é um pouco diferente, como vamos ver.

Mas vamos começar escrevendo o cabeçalho. Vamos inserir a biblioteca s t r i n g para nos ajudar.

Passo 2

Vamos desenvolver a classe P e s s o a .

Em escopo privado vamos declarar três atributos básicos n o m e , i d a d e e s a l a r i o .

Para inicializar os atributos privados vamos desenvolver um método construtor. Lembre-se que o construtor é um método sem tipo com o mesmo nome da classe. O construtor vai receber como parâmetro os valores dos atributos.

Vamos desenvolver um método t e x t o P e s s o a ( ) que imprime os atributos da classe. Esse método é útil pois será usado como parte da sobrecarga do operador.

Passo 3

O c o u t é um objeto da classe o s t r e a m , e por isso o operador deve levar isto em consideração.

O processo da sobrecarga é:

o s t r e a m &   o p e r a t o r ≪ ( o s t r e a m   & S a i d a ,   C l a s s e   O b j e t o )

No nosso caso, a classe é P e s s o a e o objeto vamos chamar de p .

Dentro do método vamos nós escrevemos todos os c o u t que queremos que sejam executados quando a sobrecarga for utilizada.

Porém, a gente foi esperto e já escreveu tudo isso dentro do método t e x t o P e s s o a , então é só executar esse método dentro da função de sobrecarga:

E pronto! Sobrecarga concluída.

Passo 4

Agora vamos testar o código

Criamos um objeto da classe P e s s o a chamado p 1 e usamos o construtor para inicializar o objeto.

Depois executamos o c o u t diretamente no objeto p 1

Rodando o código o resultado é:

E é isso! Questão concluída.

Resposta

Exercício Resolvido #7

Crie uma classe que representa um vetor de inteiros. O tamanho desse vetor deve ser definido dinamicamente no momento da criação do objeto. Efetue a sobrecarga do operador colchetes   para que a gente possa acessar facilmente um elemento do vetor.

Passo 1

Vamos nessa, pessoal.

Nesse exercício vamos trabalhar várias coisas.

A questão pede pra criar uma classe que represente um vetor, então vamos chamar essa classe de V e t o r .

Dentro da classe V e t o r vamos ter que usar um array para armazenar os elementos do nosso vetor. O detalhe é que esse array dentro da classe deve ser alocado. Se você se lembrar, a melhor forma de fazer isso é alocando a array dentro do construtor, e liberando a memória dentro do destruidor. Assim, nós garantimos que a memória dinâmica só vai existir enquanto um objeto da classe estiver ativo.

Mas além disso, esse também é um exercício de sobrecarga de operador, pois vamos sobrecarregar o operador   , pra gente poder acessar os elementos da array de forma direta.

Então vamos começar com o cabeçalho da classe:

Passo 2

Então vamos declarar a classe V e t o r , e dentro da classe vamos declarar o protótipo de todos os métodos.

Primeiro criamos a classe:

E dentro do encapsulamento privado, vamos criar os atributos necessários: o ponteiro * p n t V e t o r que vai armazenar o endereço de memória do array dinâmico, e o atributo t a m a n h o que vai armazenar a quantidade de elementos desse array dinâmico.

A questão pede que eles sejam do tipo inteiro.

Agora vamos para o encapsulamento público. Aqui vamos criar o protótipo de todas os nossos métodos

Primeiro declararmos o construtor, que vai efetuar a alocação dinâmica da array, e para isso vai receber o parâmetro t a m a n h o . Lembre-se que um construtor é um método sem tipo, com o mesmo nome da classe:

Depois declaramos o destruidor que vai liberar a memória alocada dinamicamente. Lembrando que um destruidor um método iniciado com ~ , sem tipo, sem parâmetros e com o mesmo nome da classe.

Agora vamos pensar na sobrecarga do operador   . O primeiro detalhe é que esse operador só pode ser sobrecarregado como função-membro da classe.

t i p o   o p e r a t o r   S i m b o l o D o O p e r a d o r   (   p a r a m e t r o s   )

O símbolo do operador é   , e o parâmetro que vamos receber é o índice a ser acessado. O segundo detalhe é que o tipo da função será i n t & !

Mas não perca a calma, que eu já te explico porque esse & apareceu aí...

Pronto. O protótipo da nossa classe está desenvolvido. O próximo passo é desenvolver o conteúdo dos métodos.

Passo 3

O primeiro método que vamos desenvolver é o construtor. Primeiro ele vai inicializar o parâmetro t a m a n h o :

Em seguida, alocamos no ponteiro p n t V e c t o r um array dinâmico com a dimensão t a m a n h o :

Prontinho! O array dinâmico foi criado com sucesso. Agora, vamos usar um loop f o r para pedir pro usuário preencher cada uma das posições do array:

Passo 4

Agora vamos desenvolver o destruidor, que tem função de liberar a memória que foi alocada dinamicamente. Para isso vamos usar o operador d e l e t e   [   ] para apagar o conteúdo do endereço de memória apontado por p n t V e t o r .

E é só isso. O destruidor está prontinho!

Passo 5

Agora vamos dar uma olhada detalhada na sobrecarga do operador   .

A principal função desse operador é mostrar o conteúdo existente um uma posição do array. Dentro do colchete a gente escreve um índice, e o operador sobrecarregado retorna a posição correspondente do array.

Ok, mas agora eu vou te explicar qual o motivo de usar o i n t & . Acontece que quando adicionamos o & estamos retornando uma referência ao endereço de memória! E isso é importante pois permite que a gente altere o conteúdo da array.

Veja os exemplos abaixo:

E é só isso! Usando o & no retorno da sobrecarga a gente possibilita mais usos do operador [   ] .

Com isso a classe está concluída, e só falta a gente testar.

Passo 6

Agora só falta a gente testar pra garantir que tudo funciona!

Vamos criar um objeto do tipo V e t o r e vamos inicia-lo com tamanho 5 . Assim que o objeto for criado o construtor vai entrar em ação, e vai pedir que a gente preencha o vetor.

Para fins de testes, vou imprimir o conteúdo da posição 3 . Em seguida vamos mudar o conteúdo da posição 3 para o valor 10 . E finalizamos comparando o conteúdo das posições 3 e 4 :

E pronto, vamos rodar o programa:

E o programa rodou tranquilamente. Logo de cara o construtor é acionado e podemos preencher o nosso array.

Mas o mais legal é que a gente pode visualizar, alterar e realizar operações com um elemento qualquer do vetor usando apenas o operador   , o que deixa o código muito mais limpo e simples de ler!

E veja só a última mensagem: é o destruidor entrando em ação.

E por hoje é isso! Até a próxima!

Resposta