divisão de código entre arquivos
O padrão ao se escrever em C++ aconselha a declaração de uma classe no cabeçalho e sua implementação em um arquivo .cpp. Isso, em primeiro lugar, é uma questão de organização e não uma restrição do compilador ou da linguagem.
Digamos que você queira fornecer uma biblioteca para programadores, mas não deseja mostrar como a fez, por que sua intenção é vendê-la.
O que fazer? Declarar a classe com seus métodos e atributos em um arquivo (header) e a implementação (o fonte propriamente dito) em outro. Você apenas forneceria os headers e a biblioteca.
Note que, se você usa uma biblioteca com direitos autorais contra copia, você só tem arquivos de biblioteca e arquivos headers, mas não possui a sua implementação.
Mas como funciona isso tudo?
Vocês que vem do C, sabem que o compilador da Borland requer protótipos de função. Caso ele encontre uma chamada a uma função f() que ele desconheça o protótipo, ocorre um erro.
Veja uma declaração de classe como se fosse um protótipo. Antes de qualquer implementação ser avaliada pelo compilador, ele procura pela respectiva declaração. Se não encontrá-la, gera um erro.
No entanto, para uma definição de classe contida na declaração da mesma (calma, tem um exemplo logo abaixo), o compilador não se irrita, e cria o seu ansiado arquivo-objeto.
Pensando assim, poderemos pensar no que pode ser feito.
Há algo de errado em colocar a implementação contida na definição (em apenas um arquivo)? De forma alguma. Uma nota para usuários Borland: para códigos de implementação (códigos que envolvem atribuição, implementação de métodos, etc) faca-os em um arquivo .cpp. Arquivos headers não são compilados. ( bcc32 –c arquivo.h : *ERROR* ) a não ser que se forneça um command-line option indicando ao compilador para que ele *não* reconheça arquivos .h como headers.
Ok, um arquivo .cpp contendo uma implementação de classe, sem declaração (analogamente, em C, isso é o mesmo que definir uma função antes da função main()). Não precisa declarar um protótipo extra.
//teste.cpp
//não tem “#include teste.h”, obviamente,
//já que a implementação e declaração estão aqui:
class teste
{
public:
void fazerAlgo( int x )
{
x ++;
};
private:
void NinguemMeVe()
{
int h;
h = 2;
};
};
//-----------------------EOF------------------------
Vamos complicar. Um belo dia você escreve uma classe que está grande ou pode facilmente ser modularizada, e você gostaria de dispor seus arquivos de forma mais organizada. Muito bem.
Poderia ser colocado no header a declaração dessa classe, como costumeiro, e dividir os .cpp em módulos.
Exemplo:
Automovel.h //contém a declaração da classe com 3 métodos:
//void inicializar(), void mudarMarcha(), void ligarMotor()
Automovel_inicializacao.cpp //define o método void inicializar()
Automovel_cambio.cpp //define o método void mudarMarcha()
Automovel_motor.cpp //define o método void ligarMotor()
Cada um desses arquivos .cpp seriam responsáveis por implementar um determinado conjunto de métodos declarados no Automovel.h. Cada fonte teria um #include “Automovel.h”
Aumentando a aposta: duas ou mais classes em um arquivo?
Por que não?
Que tal declarar três classes em um arquivo header e implementar as três classes em um arquivo .cpp? Ótimo.
//Arquivo: meuheader.h
#ifndef MEUHEADER
#define MEUHEADER
class biscoito
{
public:
void cozinhar();
};
class laranja
{
public:
void descascar();
};
class torrada
{
public:
void torrar();
};
#endif
//------------------EOF-----------------//
//Arquivo: definicoes.cpp
#include "meuheader.h"
#include <iostream>
using std::cout;
void biscoito::cozinhar()
{
cout << "cozinhando\n";
}
void laranja::descascar()
{
cout << "descascando\n";
}
void torrada::torrar()
{
cout << "torrando\n";
}
//-------------------EOF--------------------------
Desorganizado? Muito! funciona? Sim..........
Vamos colocar tudo em um só arquivo .cpp
//Arquivo: tudojunto.cpp
#ifndef MEUHEADER
#define MEUHEADER
#include <iostream>
using std::cout;
class biscoito
{
public:
void cozinhar()
{
cout << "cozinhando\n";
};
};
class laranja
{
public:
void descascar()
{
cout << "descascando\n";
};
};
class torrada
{
public:
void torrar()
{
cout << "torrando\n";
};
};
#endif
//-------------------------EOF------------------------
Quer usar essas classes aí em cima no seu código?
Faca um #include “tudojunto.cpp”
Também não é o ideal.
Faça as declarações das classes em um arquivo .H e reserve um arquivo .cpp para a implementação de cada classe.
A definição está muito grande? Divida a definição em seções, como explicado anteriormente. Isso tudo é a critério do programador (do seu chefe, se não for você mesmo), que deve ter o senso de organização bem apurado.
A maneira como se organiza a disposição das classes não muda o modo como o programa funciona, não muda seu código em si. É um critério de organização da implementação. Porém existem algumas limitações e regras impostas pelo pré-processador. Por exemplo, erros de inclusão circular podem ocorrer. Isso não acontece quando incluímos “guardas” nos headers:
#ifndef NOME_DA_DEFINICAO #define NOME_DA_DEFINICAO /* codigo */ #endif
Outro erro possível de aparecer é uma dependência mútua entre classes. Porém, pretendo explicar a solução para esse problema futuramente.
Jester
|
HOME || MAPA DO SITE || CURSOS || TUTORIAIS || LINKS || FORUM || CONTATO |