Recibo da Frequência de Programação Orientada para Objectos (IGE e ETI), 2º semestre de 2000/2001, ISCTE:

Nome do aluno: _______________________________________________

Número do aluno:  ______________________

Assinatura do docente: ________________________________________


Identificação

Nome do aluno: _______________________________________________

Número do aluno:  ______________________

Turma: ____________


Frequência

Programação Orientada para Objectos

IGE e ETI

2º semestre de 2000/2001

ISCTE


Notas:

 

Questão 1
Assinale com V (Verdadeiro) as expressões que estão correctas e com F (Falso) as que estão incorrectas.

Deve preencher todos os espaços indicados por um sublinhado (___) com V ou F. Qualquer espaço não preenchido será considerado como uma resposta errada.

Em geral as alíneas podem ter zero ou mais respostas correctas.  Cada resposta correctamente assinalada vale 0,5 valores.

Nas alíneas em que apenas uma resposta está correcta (se existirem estão assinaladas no texto), responder com mais ou menos do que um V anula a cotação.  A resposta correcta corresponde à cotação completa.  Qualquer outra resposta corresponde a zero valores.

Considere as seguintes classes:

class B {
  public:
    B();
    virtual ~B();
    virtual void m1() = 0;
};

class DdeB : public B {
  public:
    DdeB();
    virtual void m1();
    virtual void m2(int p);
};

class DdeD: public DdeB {
  public:
    DdeD();
    virtual void m2(int p);
};

1.1  Quais das seguintes instruções estão correctas?

__  B* b = new DdeB(); b->m1();
__  B* b = new B(); b->m1();
__  B* b = new DdeD(); b->m2(3);

[cotação: 1,5]

1.2  Quais das seguintes definições estão correctas?

__  void DdeD() { cout << "DdeD::DdeD()" << endl; }
__  DdeD() : DdeB(), B() {}
__  DdeD() : DdeB() {}

[cotação: 1,5]

1.3  Dado o seguinte código:

double a = 3.0;
int* b = 0;
float c = 3.14;
int const* d = new int[4];
int* const e = new int[5];

Quais das seguintes instruções estão correctas?

__  int* resultado = a < 3.5 ? a : 3.5;
__  b = &c;
__  ++d;
__  ++e;

[cotação: 2]

Questão 2

Recorde-se que deve ler atentamente todo o enunciado antes de resolver as questões!

Pretende-se implementar, em C++, uma aplicação para apoio à divulgação de notícias.  Esta aplicação permite aos seus utilizadores consultar e registar notícias.  São mostradas todas as notícias que se encontram na lista gerida por esta aplicação sempre que um utilizador assim o peça.

A aplicação responsabiliza-se pela actualização das notícias disponíveis para consulta, analisando diariamente as condições necessárias à disponibilização de notícias: as notícias que não verifiquem as condições são removidas da lista gerida por esta aplicação.

A definição da classe GestorDeNotícias, seguidamente apresentada, é uma simplificação da classe que gere as notícias na referida aplicação:

class GestorDeNotícias {
  public:
    GestorDeNotícias();
    ~GestorDeNotícias();

    //
Método invocado diariamente para actualizar as notícias:
    void actualiza(Data const& data_actual);

    void registaNotícia(Notícia* notícia);
    void cancelaAcontecimento(int identificação);

    //
O parâmetro nome é o nome do utilizador que respondeu ao anúncio:
    void registaRespostaAAnúncio(string const& nome, Data const& data_da_resposta);

    //
Método invocado quando o utilizador pede a lista de notícias:
    void mostra() const;

  private:
    list<Notícia*> noticias;
};

Cada notícia contém:

Existem dois tipos concretos de notícias: anúncios e divulgação de acontecimentos.

Os anúncios são notícias que requerem uma resposta.  A disponibilização de um anúncio, que no máximo dura todo o intervalo de validade, cessa logo que algum utilizador lhe responde.  Cada anúncio contém o nome do utilizador que lhe respondeu e a data em que tal aconteceu.  Esta informação é enviada a outro sistema antes da remoção do anúncio (esta operação não é da responsabilidade desta aplicação).

A divulgação de acontecimentos é uma notícia que indica a realização de um evento (e.g., um seminário).  Os acontecimentos são noticiados durante todo o intervalo de validade definido.

Os acontecimentos podem ser cancelados.  Nesse caso os acontecimentos continuam a ser noticiados até expirar o prazo de validade do acontecimento alertando, no entanto, para o seu cancelamento.

Considere a existência de uma classe Data onde se encontram todas operações de que necessite para a resolução destas perguntas desta questão.

2.1  Defina as classes Notícia, Anúncio e AcontecimentoNão é necessário nesta alínea definir quaisquer métodos das classes.

[cotação: 3]
 
2.2  Assuma que a invocação do método void Notícia::mostra() const faz aparecer informação no ecrã com o seguinte aspecto:

Identificação: 1
Título: Prova de kart
Descrição: Informa-se que dia 2001/07/07 decorrerá uma prova de kart no kardódromo de Palmela.
Fonte: Bruno Abreu
Data de registo: 2001/07/02
Data inicial de transmissão: 2001/07/03
Data final de transmissão: 2001/07/06

Implemente o método void Acontecimento::mostra() const, que mostra no ecrã informação relativa a um acontecimento. Caso o acontecimento tenha sido cancelado, a informação enviada para o ecrã tem o seguinte aspecto:

CANCELADO: 2001/07/04
Identificação: 1
Título: Prova de kart
Descrição: Informa-se que dia 2001/07/07 decorrerá uma prova de kart no kardódromo de Palmela.
Fonte: Bruno Abreu
Data de registo: 2001/07/02
Data inicial de transmissão: 2001/07/03
Data final de transmissão: 2001/07/06

Caso o acontecimento não tenha sido cancelado, a informação enviada para o ecrã tem o seguinte aspecto:

Identificação: 1
Título: Prova de kart
Descrição: Informa-se que dia 2001/07/07 decorrerá uma prova de kart no kardódromo de Palmela.
Fonte: Bruno Abreu
Data de registo: 2001/07/02
Data inicial de transmissão: 2001/07/03
Data final de transmissão: 2001/07/06

[cotação: 2] 

2.3  Implemente o destrutor da classe GestorDeNotícias.  Este método é responsável pela destruição de todas as variáveis dinâmicas contidas nesta classe, tenham ou não sido criadas dentro dela (i.e., pelos seus métodos).

[cotação: 2]

2.4  Implemente o método void GestorDeNotícias::actualiza(Data const& data_actual).  Este método é responsável por actualizar as notícias disponíveis na aplicação.  Lembre-se que esta aplicação é responsável pela actualização das notícias disponíveis para consulta, analisando diariamente as condições necessárias à disponibilização de notícias: as notícias que não verifiquem as condições são removidas da lista gerida por esta aplicação.  Implemente todos os métodos das classes Notícia, Anúncio e Acontecimento que forem necessários.

[cotação: 3]

Questão 3

Implemente o método void ListaDouble::transfereDe(ListaDouble& outra_lista), pertencente à classe ListaDouble, cuja definição é fornecida em anexo.  O método em questão transfere todos os itens de outra_lista para o fim da lista implícita.  A outra_lista fica vazia.  Não use as classes iteradoras na implementação deste método: use manipulações de ponteiros.  Use tão poucas manipulações de ponteiros quanto possíveis.

A implementação da lista baseia-se no conceito de cadeia duplamente ligada com guardas.

[cotação: 3]
 
Questão 4

Exemplifique sumariamente o lançamento e a captura de uma excepção em C++ e explique para que servem e em que circunstâncias devem ser usadas.

[cotação: 2]

Anexo 1

Definição da classe ListaDouble:

#ifndef LISTA_DOUBLE_H
#define LISTA_DOUBLE_H

#include <iostream>

/**
@brief Representa listas de itens do tipo Item.

   
Item é actualmente é um sinónimo de double, mas que pode ser alterado 
    facilmente para o tipo que se entender.  Por convenção, chama-se "frente"
    e "trás" ao primeiro e último item na lista.  Os nomes "primeiro", "último",
    "início" e "fim" são reservados para iteradores.

    @invariant 0 < numero_de_itens. */
class ListaDouble {
  public:
    typedef double Item;

    class Iterador;
    class IteradorConstante;

    ListaDouble();
    ~ListaDouble();

    Item const& frente() const;
    Item const& trás() const;

    int comprimento() const;

    bool estáVazia() const;
    bool estáCheia() const;

    IteradorConstante primeiro() const;
    IteradorConstante último() const;
    IteradorConstante início() const;
    IteradorConstante fim() const;

    IteradorConstante primeiraOcorrênciaDe(Item const& item) const;
    IteradorConstante últimaOcorrênciaDe(Item const& item) const;

    Item& frente();
    Item& trás();

    void põeNaFrente(Item const& novo_item);
    void põeAtrás(Item const& novo_item);

    void insereAntes(Iterador const& iterador, Item const& novo_item);
    void insereAntes(IteradorConstante const& iterador, Item const& novo_item);

    void tiraDaFrente();
    void tiraDeTrás();

    void esvazia();

    void remove(Iterador& iterador);
    void remove(IteradorConstante& iterador);

    void remove(Iterador const& iterador);
    void remove(IteradorConstante const& iterador);

    void transfereDe(ListaDouble& outra_lista);

    ListaDouble& operator += (ListaDouble const& outra_lista);

    Iterador primeiro();
    Iterador último();
    Iterador início();
    Iterador fim();

    Iterador primeiraOcorrênciaDe(Item const& item);
    Iterador últimaOcorrênciaDe(Item const& item);

private:

    bool cumpreInvariante() const;

    void poe(Elo* elo_anterior, Elo* elo_seguinte, Item const& novo_item);
    void tira(Elo* elo_a_tirar);

    struct Elo {
        Elo(Elo* anterior = 0, Elo* seguinte = 0, Item const& item = Item());
        Item item;
        Elo* anterior;
        Elo* seguinte;
    };

    int número_de_itens;

    Elo* elo_inicial;
    Elo* elo_final;

    friend Iterador;
    friend IteradorConstante;
};

/**
@brief Operador de inserção de listas num canal.

    Todos os itens da lista são inseridos por ordem entre parênteses e separados por vírgulas. */
std::ostream& operator << (std::ostream& saída, ListaDouble const& lista);

#include "lista_double_impl.H"

#endif // LISTA_DOUBLE_H