Os alunos no final desta aula deverão conhecer:
Deverão também ser capazes de:
Caso os alunos sintam que os objectivos não foram atingidos na totalidade deverão concluir/repetir os exercícios desta aula autonomamente e ou recorrer aos horários de dúvidas.
Os ficheiros relativos a esta aula estão disponíveis no arquivo Aula6.zip.
ListaDeDouble
com iteradores constantes desenvolvida na Aula
5 (ficheiros lista_de_double.H,
lista_de_double_impl.H e
lista_de_double.C). Pode encontrar os ficheiros no directório ~/POO/Aula6.1.a) O construtor da classe tem um problema. Se a construção
da guarda final falhar é lançada uma excepção
bad_alloc
e a guarda inicial nunca é destruída! Corrija o problema
capturando a excepção e relançando-a (para relançar
uma excepção basta escrever throw;). Talvez
seja necessário passar os ponteiros para as guardas a variáveis
(neste momento são constantes).
1.b) A construção de uma lista à custa de
outra usando o construtor por cópia fornecido implicitamente pela
linguagem tem os mesmos problemas graves que para a classe PilhaDeInt
discutida no resumo e na aula teórica. Em particular, a lista construída partilha
os seus elos dinâmicos com a que lhe serve de original, o que é
claramente incorrecto. Implemente um construtor por cópia
que resolva o problema. Garanta que todas as variáveis dinâmicas
são destruídas se a memória faltar a meio da construção
ou se for lançada uma excepção durante a cópia dos itens.
1.c)
Reimplemente o método ListaDeDouble::poe() de forma a garantir que,
em caso de lançamento de uma excepção, a pilha em causa fica não apenas num estado válido, mas
exactamente no mesmo estado em que estava imediatamente antes de a operação
ser invocada (ou seja, a garantia forte da segurança face a excepções).
1.d) A atribuição entre duas listas é impossível
se existirem as duas constantes membro de instância da solução
original: elo_inicial e elo_final. Mesmo que se passem
essas constantes a variáveis, a atribuição tem os
mesmos problemas da construção por cópia. Implemente
um operador de atribuição por cópia que resolva o
problema. Garanta que os elos dinâmicos dos itens na lista
original são destruídos. Não se preocupe para já com
as garantias de segurança face a excepções.
Discuta como poderia melhorar o código produzido de modo a fornecer os vários níveis de segurança face a excepções.
1.e) Melhore o operador de atribuição por cópia de modo a fornecer a garantia forte de segurança face a excepções. Comece por fornecer a com garantia básica. Depois forneça a garantia forte.
1.f) Defina uma nova
operação ListaDeDouble::trocaCom() que troque todos os seus itens
com a lista passada como argumento. Recorra ao procedimento std::swap()
(#include <algorithm>).
1.g) Reimplemente o operador de atribuição por cópia de modo a usar a nova operação.
1.h)
Usando a mesma ideia, reimplemente o operador de concatenação de listas de
modo a fazer uso da operação ListaDeDouble::transfereDe().
2. Relativamente à versão final do módulo
das pilhas apresentado no resumo (ficheiros pilha_int.H, pilha_int_impl.H e pilha_int.C,
no directório ~/POO/Aula6):
2.a) Passe para um método auxiliar o código de
alteração da capacidade da pilha. I.e., acrescente uma operação
privada PilhaDeInt::Item* PilhaDeInt::novosItens(int capacidade) que
construa e devolva uma matriz dinâmica com a capacidade recebida como argumento
e contendo cópias dos itens da pilha. Adopte e adapte parte do código do
método PilhaDeInt::põe().
2.b) Reimplemente o método PilhaDeInt::põe()
e o construtor por cópia à custa do novo método privado que criou. Deve
sempre fornecer a garantia forte de segurança face a excepções.
2.c) Reescreva o procedimento
PilhaDeInt::tira() de modo a reduzir
a capacidade da pilha para metade sempre que a ocupação estiver a 25% ou menos. Não deixe nunca que a
capacidade seja reduzida abaixo da capacidade inicial. Este método não pode
falhar pelo simples facto de não se ter conseguido reduzir a capacidade!
2.d)
Forneça a classe de uma operação PilhaDeInt::trocaCom()
que troque o conteúdo da pilha com o de outra pilha passada como
argumento. Implemente o operador de atribuição por cópia à custa desta
nova operação. Explique porque é que a nova implementação fornece a
garantia forte de segurança face a excepções.