Exercícios Resolvidos de Templates

Ver Teoria

Enunciado

Crie um template de classe que representa um vetor de qualquer tipo. 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 envolve um monte de conhecimentos: templates, alocação dinâmica e sobrecarga de operador. É bastante coisa! Mas vai ser divertido fazer essa questão.

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

Dentro do template V e t o r vamos ter que usar um array alocado dinamicamente para armazenar os elementos do nosso vetor. Se você se lembrar, a melhor forma de fazer isso é alocando a array dentro do construtor, e liberando a memória dentro do destruidor. Depois vamos sobrecarregar o operador   .

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

Passo 2

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

Para criar um template de classe a gente utiliza a palavra-chave t e m p l a t e e determinamos um tipo genérico usando t y p e n a m e e em seguida declaramos a classe:

t e m p l a t e < t y p e n a m e   N o m e T i p o G e n e r i c o > c l a s s   N o m e C l a s s e

Template iniciado. Agora vamos pro encapsulamento privado, e declaramos o atributo ponteiro p n t V e t o r usando o tipo genérico T . Afinal de contas, é esse ponteiro que vamos usar para alocar a memória dinamicamente, então ele precisa apontar para o tipo que vamos utilizar no nosso template.

O tamanho do V e t o r sempre será um valor inteiro, então criamos um atributo t a m a n h o que vai armazenar a quantidade de elementos do V e t o r .

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

Primeiro declararmos o construtor, que é um método sem tipo, e que vai receber o valor inteiro de t a m a n h o . Ou seja, é só declarar um construtor normalmente.

Depois declaramos o destruidor, que também é um método sem tipo, então é só declarar um destruidor normalmente.

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á T & !

O tipo é T pois o operador vai retornar um elemento do V e t o r e o tipo dos elementos do V e t o r são determinados de acordo com o tipo genérico do template. O símbolo & está aí, pois queremos retornar uma referência para o valor do V e t o r , isso torna possível que o valor seja alterado se necessário.

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

Passo 3

O primeiro método que vamos desenvolver é o construtor.

Aqui temos que notar uma pequena diferença. Quando queremos desenvolver um método que foi declarando dentro de um template, nós temos que adicionar o prefixo de template, e antes do operador temos que adicionar os tipos genéricos entre chaves.

Ou seja, um método de template tem que ser escrito que nem um template de função, mas adicionando o nome da classe com o operador , da seguinte forma:

t e m p l a t e   < t y p e n a m e   T >   t i p o   N o m e C l a s s e < T > : : N o m e M e t o d o (   p a r a m s   )

O construtor é um método sem tipo de retorno e com o mesmo nome da classe, então fica assim:

t e m p l a t e   < t y p e n a m e   T >   V e t o r < T > : : V e t o r ( i n t   t a m a n h o )

Dentro do construtor, a primeira coisa a ser feita é 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. Novamente precisamos lembrar que um método de template tem que ser escrito que nem uma função template, mas adicionando o nome da classe e o operador , da seguinte forma:

t e m p l a t e   < t y p e n a m e   T >   t i p o   N o m e C l a s s e < T > : : N o m e M e t o d o (   p a r a m s   )

Dentro do destruidor temos que 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   . Novamente, quando escrevemos um um método de template precisamos adicionar os prefixos de template:

t e m p l a t e   < t y p e n a m e   T >   t i p o   N o m e C l a s s e < T > : : N o m e M e t o d o (   p a r a m s   )

No caso da sobrecarga do operador   o tipo de retorno é T & .

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.

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 criar um outro objeto da classe V e t o r , mas dessa vez usando o tipo f l o a t . E vamos imprimir a primeira posição desse objeto.

E pronto, vamos rodar o programa:

E o programa rodou tranquilamente. Como estamos usando templates, foi super tranquilo alterar o tipo de dados usado no Vetor!

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

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

Resposta