Recibo, exame tipo, 2ºsemestre de 1998/99, 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 tipo

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.

Qualquer alínea pode ter zero ou mais respostas correctas.  Cada resposta correctamente assinalada vale 0,5 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 X {
  public:
    X();
    ...
};

class A {
    int a;
    X* px;
  public:
    int ay;
    A(int);
    virtual void g() const {
        cout << "Execução de A::g(). ";
    }
    ...
};

class B : public A {
  public:
    int bx;
    B(int, int);
    void g() const {
        A::g();
        cout << "Execução de B::g(). ";
    }
    ...
};

int main() {
    ...
}

Questão 1.1
 Quais dos seguintes construtores inicializam correctamente todas as variáveis privadas da classe A?
__ A::A(int aa) : a(aa), px(X) {}
__ A::A(int aa) {a = aa; px = X;}
__ A::A(int aa) : a(aa), px(new X) {}
[1.5 valores]
Questão 1.2
Dadas as seguintes declarações:
A* a = new A;
B b;
Quais das seguintes instruções são correctas?
__ A->ay = 1;
__ b.ay = 1;
__ b.a = 1;
__ b.bx = 1;
[2 valores]
Questão 1.3
 Para que apareça no ecrã exactamente
Execução de A::g(). Execução de B::g().
quais as instruções que é necessário executar?
__ A::g(); B::g();
__ A a; a.g(); B b; b.g();
__ B b; b.g();
[1.5 valor]
Questão 2
Considere o seguinte código:
template <typename Item>
class Pilha {
  public:
    Pilha();                    // construtor da classe.
    void põe(const Item& item); // coloca item no topo da pilha.
    void tira();                // retira o item do topo da pilha.
    Item topo() const;          // devolve o item no topo da pilha.
    bool vazia() const;         // devolve true sse a pilha estiver vazia.
    bool cheia() const;         // devolve true sse a pilha estiver cheia.
    int tamanho() const;        // devolve o número de itens na pilha.
  private:
    static const int limite = 100;
    Item itens[limite];
    int quantos;
};

enum Naipe {copas, paus, espadas, ouros};
enum Valor {duque, terno, quadra, quina, sena,
            manilha, oito, nove, dez, valete, dama, rei, ás};

class Carta {
    Naipe naipe_;
    Valor valor_;
  public:
    Carta(Naipe naipe, Valor valor);
    Carta();
    Naipe naipe() const;
    Valor valor() const;
};
operator > (const Carta& a, const Carta& b);

Questão 2.1
Defina o operador > para a classe Carta.  Pode assumir que as cartas são comparadas apenas pelo seu Valor.  A ordem de valores a usar é a da sueca (mas incluindo oitos, noves e dezes).  Ou seja: duque, terno, quadra, quina, sena, oito, nove, dez, dama, valete, rei, manilha, ás.

[3 valores]

Questão 2.2
Assuma que o construtor por omissão da classe Carta gera aleatoriamente um naipe e um valor para cada carta criada.  Crie um pequeno programa que crie 4 pilhas de 52 cartas, e um matriz com 4 inteiros chamada pontuações. De seguida o programa deve fazer um ciclo que desempilhe uma carta de cada pilha, compare os seus valores e some um ponto à pontuação respectiva, i.e., se o valor da carta tirada da primeira pilha for o maior, deve ser incrementado o valor de pontuações[0], etc.

No fim o programa deve escrever uma mensagem indicando quem venceu e porquê:

Venceu o jogador 2 com 16 cartas mais altas em 52 jogadas.
[2 valores]
Questão 3
Pretende-se modelar parte de um sistema de gestão de contas bancárias de um banco.  É necessário representar o conceito de conta.  Todas as contas possuem um saldo (em escudos) e uma taxa de juro, e permitem creditar, debitar, ver o saldo, alterar a taxa de juro e calcular o juro (para simplificar o juro pode ser calculado simplesmente como o produto da taxa de juro pelo saldo).

Existem apenas dois tipos concretos de conta: à ordem e a prazo.

Nas contas a prazo só é possível levantar a totalidade do saldo, não podendo ser feitos quaisquer débitos de partes do saldo.  Nestas contas só podem ser efectuados créditos superiores a 100 000$.

As contas à ordem devem guardar informação sobre o limite mínimo a que a conta pode chegar.  Este limite pode ser um número negativo, admitindo-se nesse caso que o cliente tem alguma margem de crédito.  As contas à ordem não devem permitir débitos que reduzam o saldo para além do limite mínimo.  Por exemplo, se o limite de crédito para determinada conta à ordem é de -20 000$ e o saldo é de 100 000$ deve ser permitido um débito até 120 000$, mas nunca um débito superior a esse valor.

As contas a prazo devem inicializar a taxa de juro, por omissão, com o valor 0,03 (3%) e as contas à ordem com o valor 0,01 (1%).

As funções de crédito e débito devem devolver o valor o valor efectivamente creditado ou debitado.  Por exemplo, se uma conta à ordem tiver um saldo de 50 000$ e limite de saldo de -10 000$, uma tentativa de debitar 100 000$ (através da invocação da função apropriada) terá como resultado um débito de 60 000$, valor esse que deve ser devolvido pela função respectiva.  Uma tentativa de débito de 1$ de uma conta a prazo com saldo de 200 000$ resultará num débito de 200 000$, sendo este o valor devolvido pela função respectiva.  Uma tentativa de crédito de 5 000$ numa conta a prazo resultará num crédito de 0$, sendo este o valor devolvido pela função respectiva.

Defina totalmente a classe abstracta Conta que representa aquilo que é comum a todas as contas.

[2 valores]

Defina totalmente as classes ContaÀOrdem e ContaAPrazo.

[4 valores]

Questão 4
Implemente um procedimento void ordena(int m[], int n) que ordene uma matriz m contendo n inteiros usando uma das possíveis versões do algoritmo de ordenação por permutação ou bolha (bubble sort).

[2 valores]

Questão 5
Dada a declaração:
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.
};

implemente uma função void remove(Nó*& primeiro, Nó*& ultimo, Nó* nó) que deve remover um nó da lista simplesmente ligada e sem guardas com o endereço do primeiro nó dado por primeiro e o endereço do último nó dado por último.  O parâmetro contém o endereço do nó a remover.  Os ponteiros primeiro e último, para o primeiro e último elemento respectivamente, devem ser alterados se necessário.

Tenha em atenção que a estrutura não tem ponteiro para o nó anterior (lista simplesmente ligada) e que os nós endereçados por primeiro e último não são guardas, i.e., contêm informação útil.

[2 valores]

Questão 6
Explique sucintamente em que circunstâncias deve ser utilizada herança privada e quais as consequências da utilização desse tipo de herança.

[2 valores]