Aula prática 1

Sumário

Objectivos

Os alunos no final desta aula deverão conhecer:

  1. Os conceitos associados a modularização física e compilação separada:
  2. As várias fases de construção de um ficheiros executável a partir dos ficheiros fontes.
  3. As directivas de processamento básicas (#define#ifndef/#endif, #ifdef/#endif e #include).
  4. A noção de espaço nominativo.

Deverão também ser capazes de:

  1. Desenvolver pequenos programas divididos por vários módulos físicos.
  2. Proteger os ficheiros de interface dos efeitos das inclusões múltiplas.
  3. Criar ficheiros de construção simples e usar o construtor (make
  4. Criar e usar ficheiros de arquivo.
  5. Usar espaços nominativos.

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.

Material de apoio

Os ficheiros relativos a esta aula estão disponíveis no arquivo codigo.zip.

Exercícios

Comece por configurar o acesso ao grupo poo-iscte no Yahoo!.  Veja O grupo poo-iscte do Yahoo! na página sobre Metodologia.

Algumas das perguntas que se seguem não exigem programação.  Para guardar as respectivas respostas sugere-se que use um ficheiro auxiliar, por exemplo ~/POO/Aula1/Aula1.txt.

Caso tenha dúvidas em relação a algumas das perguntas teóricas pode consultar o Capítulo 9 das folhas teóricas.


1.  O que entende por pré-processamento, compilação e fusão? 

No seu directório ~/POO/Aula1 encontra o ficheiro de implementação aluno_tudo_junto.C.

1.a)  Qual o comando para pré-processar o ficheiro de implementação aluno_tudo_junto.C, gerando a respectiva unidade de tradução (aluno_tudo_junto.ii)?  Experimente.

1.b)  Qual o comando para compilar a unidade de tradução aluno_tudo_junto.ii, gerando o respectivo ficheiro objecto?  Experimente.

1.c)  O ficheiro resultante da alínea anterior é executável?

1.d)  Qual o comando para fundir o ficheiro objecto aluno_tudo_junto.o com os arquivos da biblioteca padrão de modo a gerar o ficheiro executável? Experimente.

1.e) Qual a linha de compilação a usar para criar o ficheiro executável directamente a partir do ficheiro de implementação aluno_tudo_junto.C? Experimente.


2.  O que se entende por directiva de pré-processamento?

2.a)  Qual o objectivo da directiva #define?

2.b)  Qual o objectivo de cada uma das seguinte directivas:

2.c)  Qual o objectivo da directiva #include?

2.d)  No seu directório ~/POO/Aula1 encontra o ficheiro de implementação funcionario.C.  Pré-processe-o e comente os resultados, dizendo nomeadamente:


3.  Considere a classe Aluno definida no ficheiro aluno_tudo_junto.C.

3.a)  Distribua o código pelos ficheiros adequados de um novo módulo aluno:

3.b)  Use a classe Aluno nos seguintes programas, cujo código fonte se encontra nos ficheiros procura.C e media.C, sem duplicar o código da classe Aluno.

A existência de uma função main() no ficheiro de implementação de um módulo físico justifica-se para a realização de testes sobre as ferramentas definidas nesse módulo (teste do módulo físico, que pode ser separado em testes das suas várias ferramentas).  Esta função não pode ser considerada na compilação normal, devendo apenas ser visível aquando da realização de testes.

3.c)  Coloque a função main() contida no ficheiro aluno_tudo_junto.C no ficheiro aluno.C.  Use directivas de compilação para poder controlar a visibilidade da função main() durante a  construção do programa.

Nota:  A directiva #define X  pode substituir-se pela opção de pré-processamento -DX:

c++ -Wall -ansi -pedantic -g -DTESTE -o módulo módulo.C


4.  A construção dos programa exige uma sequência de comandos.  Como simplificar este processo de modo a  evitar a introdução manual dos vários comandos e de modo a que na construção sejam pré-processados, compilados e fundidos apenas os ficheiros afectados pelas alterações realizadas desde a última construção?  Para isso é conveniente construir um chamado ficheiro de construção (makefile).

Estes ficheiros, que normalmente se chamam Makefile, servem para automatizar e optimizar o processo de compilação.  Por exemplo, é desejável que, se só se alterou o ficheiro media.C, não seja recompilado o ficheiro procura.C.

4.a)  Use o ficheiro de construção Makefile que pode encontrar em ~/POO/Aula1.

Atenção!  Ao copiar este ficheiro pode invalidá-lo!  Todas as suas linhas devem estar totalmente chegadas à esquerda (sem espaços), com excepção das linhas de comandos, que devem ter exactamente um tabulador no seu início.

Apague todos os ficheiros objecto (rm *.o) e execute o seguinte comando:

make

Magia!  Funciona!  Experimente agora alterar alguma coisa no ficheiro de implementação media.C.  Repita o comando make.  O comando percebeu que só precisava de pré-processar e compilar de novo esse ficheiro de implementação e de fundir de novo os ficheiros objecto produzindo o ficheiro executável media.


5.  Considere a classe Pauta definida no módulo pauta, que consiste nos ficheiros pauta.C, pauta.H e pauta_impl.H (em ~/POO/Aula1/) e o módulo aluno anteriormente definida.  O ficheiro de implementação pauta.C contém uma função main() de teste.

5.a)  Acrescente o ficheiro de construção (Makefile) de modo a construir o ficheiro executável teste_pauta, a partir dos módulos aluno, pauta e teste_pauta (este último apenas com ficheiro de implementação teste_pauta.C, de novo em ~/POO/Aula1/).

5.b)  Identifique os erros surgidos durante a construção, corrija-os, construa o programa e execute-o.


6.  O que é um espaço nominativo?

6.a)  Como se definem ferramentas como pertencentes a um espaço nominativo?

6.b)  Como se usam ferramentas de um espaço nominativo fora dele?

6.c)  Considere as novas classes Tuna, definida no módulo tuna (ficheiros tuna.H e tuna_impl.H) e Pauta, definida no módulo pauta_musical (ficheiros pauta_musical.C, pauta_musical.H e pauta_musical_impl.H).  Corrija os erros que impedem a compilação do módulo teste_pauta_musical.C, sem mudar o nome de nenhuma das classes.


7.  Se pretender fornecer vários módulos físicos incluídos numa biblioteca para reutilização noutros projectos sem fornecer o respectivo ficheiro de implementação e sem que seja necessário indicar explicitamente os respectivos ficheiros objecto durante a construção dos ficheiros executáveis que deles dependem, que solução se pode usar?

7.a)  O que é um ficheiro de arquivo?

7.b)  Como se cria um ficheiro de arquivo?

7.c)  Como se usa um ficheiro de arquivo?

7.d)  Suponha que pretende integrar os módulos físicos aluno e pauta numa biblioteca escola.  Crie o ficheiro de arquivo libescola.a da biblioteca contendo os ficheiros de arquivo aluno.o e pauta.o.

7.e) Construa o programa média usando um comando de fusão que não indique explicitamente o ficheiro objecto aluno.o, mas sim o ficheiro de arquivo da biblioteca libescola.a.