Recibo, Exame, 2º semestre, 1998/1999, Programação II/Programação Orientada por Objectos, ISCTE:
Nome: _______________________________________________
Nº ______________________
Ass. Docente: ________________________________________

Identificação

Nome: _______________________________________________
Nº ________________
Turma: ____________

ISCTE - IGE/ETI

Programação II /Programação Orientada por Objectos

Exame de 1ª época

1998/1999, 2º semestre


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 (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.

Em todos os casos em que não é explicitamente referida a localização de uma instrução, considere que esta é dada na função main() do programa seguinte:

class A {
    int a;
  public:
    A(int aa) : a(aa) {
    }
    virtual void f() {
        cout << "A ";
    }
    virtual void g() = 0;
};

class B : public A {
  public:
    int bx;
    B();
    B(int);
    void f() {
        A::f();
        cout << "B ";
    }
    void g() {
        f();
        cout << "C ";
    }
};

int main() {
    ...
}


 
 
 
 
Questão 1.1
 Quais das seguintes sequências de instruções estão correctas? (Têm de estar correctas todas as instruções!)
__ B* p = new B; B->bx = 1;
__ B* p; p->bx = 1;
__ B a; B& b = a; b.bx = 1;
[1,5 valores]
 Questão 1.2
Quais dos seguintes construtores da classe B inicializam correctamente a variável membro A::a?
__ B::B(int aa) { a = aa; }
__ B::B(int aa) : A(aa) {}
__ B::B(int aa) : a(aa) {}
__ B::B(int aa) { A(aa); }
[2 valores]
 Questão 1.3
Após a execução das seguintes instruções:
A* a = new B;
a->g();
o que aparece no ecrã (só uma opção verdadeira)?

___ A B C
___ A C
___ Não dá para executar o programa porque dá erro de compilação na classe B.

[1,5 valor]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 2
Considere a definição de um modelo para listas apresentada em anexo.  Considere o seguinte esqueleto para uma classe representando processos de um sistema operativo:
class Processo {
  public:
    // Construtores da classe:
    Processo();
    Processo(..., int prioridade);

    // Devolve a prioridade do processo (0 é prioridade máxima, 100 mínima):
    int prioridade() const;

    ...
};

Questão 2.1
Defina uma classe FilaPrioritária, usando a classe modelo Lista em anexo, que guarde processos da classe Processo definida acima de acordo com a sua prioridade.  Os processos têm definida uma função membro int prioridade() const que devolve um número inteiro entre 0 e 100.  Consideram-se mais prioritários os processos para os quais esta função devolva um valor menor.

O método void FilaPrioritária::tira() retira sempre o processo da frente da fila, i.e., o processo mais prioritário ou, caso exista mais do que um com a mesma prioridade, o que tiver sido colocado na fila em primeiro lugar.

O procedimento de inserção void FilaPrioritária::põe(const Processo& processo) deve colocar o novo processo de modo a que os processos na fila continuem organizados por prioridade e de tal modo que, para processos com a mesma prioridade, o primeiro a entrar na fila seja sempre o primeiro a sair.

Não precisa de definir nesta alínea quaisquer das funções ou procedimentos membro da classe, mas deve declarar todas as funções e procedimentos membro que devam constar na interface da classe, incluindo as correspondentes às operações usuais com filas.

[2 valores]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 2.2
Defina o procedimento void FilaPrioritária::põe(const Processo& processo).

[2 valores]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 3
Um dos problemas clássicos dos sistemas operativos é o da reserva e libertação de memória.
Questão 3.1
Defina uma classe Memória que tenha uma matriz de 1024 inteiros, inicializados com zeros, e que forneça ao utilizador duas operações:
int Memória::reserva(int tamanho);
void Memória::liberta(int endereço);
Quando é pedida uma reserva de memória, o programa deve procurar um bloco contíguo de memória livre do tamanho requerido pelo utilizador.  Caso não exista um bloco contíguo do tamanho necessário a função deverá devolver -1.  Caso exista um bloco nessas condições deve ser devolvido o índice da posição inicial desse bloco (o seu endereço) e deve ser escrito na posição de memória indicada por esse índice o número de posições reservadas a partir desse ponto.  Deve-se verificar se o tamanho passado como argumento tem um valor aceitável (i.e., maior que 0 e menor ou igual a 1024).

Ao libertar a memória deve ser verificado se o conteúdo da posição indicada pelo utilizador tem um número diferente de zero e, nesse caso, deve ser posto de novo a zero indicando que o bloco previamente reservado se encontra agora livre.  Se a posição indicada contiver zero, então deve ser emitida uma mensagem de erro assinalando tentativa de libertar um bloco não reservado.  Deve-se verificar se o endereço passado como argumento é válido (i.e., maior ou igual a 0 e menor que 1024).

Não precisa de definir quaisquer das funções ou procedimentos membro da classe nesta alínea.

[2 valores]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 3.2
Defina o método int Memória::reserva(int tamanho).  Não se preocupe com a eficiência na ocupação da memória.

[2 valores]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 4
Dada a declaração da estrutura para implementação de listas simplesmente ligadas:
struct Nó {
    typedef int Item;

    // Não existe ponteiro para o nó anterior!
    Nó* seguinte;      // ponteiro para o nó seguinte.
    Item item;         // guarda o item propriamente dito.

    // Construtor:
    Nó(Nó* s, const Item& i) : seguinte(s), item(i) {
    }
};

implemente ao procedimento void põeFim(Nó*& primeiro, Nó*& último, const Item& i) que deve inserir o item dado como argumento no fim da lista simplesmente ligada com primeiro nó apontado por primeiro e último apontado por último.  Tenha em conta que os nós apontados por primeiro e último não são guardas, i.e., contêm informação relevante.  Tenha também em conta que, se a lista ligada estiver vazia, ambos os ponteiros são nulos.

[2 valores]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 5
Assuma que está completamente definida a classe Tarefa :
class Tarefa {
  public:

    // Construtor (não há construtor por omissão):
    Tarefa(std::string descrição, std::string notas);

    // Destrutor virtual:
    virtual ~Tarefa() {}

    // Acesso à descrição e às notas:
    std::string descrição() const;
    std::string notas() const;

    // Devolve duração da tarefa (em dias):
    virtual int duração() const = 0;

    // Devolve custo da mão de obra da tarefa (em escudos):
    virtual int custoMãoObra() const = 0;

    // Devolve custo do material da tarefa (em escudos):
    virtual int custoMaterial() const = 0;

  private:
    std::string descrição_;
    std::string notas_;
};

Defina uma classe concreta TarefaAdministrativa (derivada da classe Tarefa) que não requeira qualquer material.  Este tipo de tarefas deve guardar o custo da mão de obra de um funcionário administrativo por dia e a duração da tarefa, para além da descrição e notas já previstas na classe Tarefa.

Defina também a função int TarefaAdministrativa::custoMaterial().  Não é necessário nesta alínea implementar qualquer das outras funções ou procedimentos membro da classe TarefaAdministrativa.

[3 valores]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Questão 6
Explique sucintamente as vantagens da utilização de guardas nas listas ligadas.

[2 valores]