PDA

Visualizza la versione completa : file header???????????


zorz
14-09-2002, 10:41
salve a tutti..mi dispiace rompere i '...' ogni 5 min ma i problemi e dubbi, quando si entra in un nuovo mondo sono tanti..anche per chi gi sa programmare no??..ebbene..stavo leggendo la guida dedicata al C++ di HTML e mi sono bloccato ad un punto..eccolo:

------------------------
E' buona norma di programmazione inserire la definizione di una classe in un file header (i file intestazione, con estensione ".h") anche se non indispensabile. Tutte le implementazioni dei metodi della classe andranno, invece, inseriti nel file con estensione cpp.

Vediamo un esempio di una semplice classe:


// Semplice esempio di una classe C++
class Cliente
{
public:
char nome[20];
char cognome[20];
char indirizzo[30];
void inserisci_nome( );
void inserisci_cognome( );
void inserisci_indirizzo( );
};




Nella classe precedente sia gli attributi che le funzioni membro della classe sono tutti public, ovvero sono accessibili da ogni punto del programma.
Adesso salviamo la classe appena definita in un file chiamata cliente.h e creiamo un nuovo file, che chiamiamo cliente.cpp, in cui andiamo a scrivere l'implementazione dei metodi. Il file cliente.cpp sar cos fatto:

#include <iostream.h>
include "cliente.h"

void Cliente::inserisci_nome( )
{
cout << Inserire il nome del dipendente: ";
cin >> nome;
cout << endl;
}

void Cliente::inserisci_cognome( )
{
cout << Inserire il cognome del dipendente: ";
cin >> cognome;
cout << endl;
}

void Cliente::inserisci_indirizzo( )
{
cout << Inserire l' indirizzo del dipendente: ";
cin >> indirizzo;
cin >> get(newline); //elimina il Carriage Return
}


main( )
{
Cliente cliente;
cliente.inserisci_nome( );
cliente.inserisci_cognome( );
cliente.inserisci_indirizzo( );
cout << "Il nome del cliente inserito :
" << cliente.nome << endl;

cout << "Il cognome del cliente inserito :
" << cliente.cognome << endl;

cout << "L' indirizzo del cliente inserito :
" << cliente.indirizzo << endl;
}

---------------------------------------------
:dh: :dh:
DOMANDINE:
1.Cos' un file 'header'??
2.Riga 2: 'include "cliente.h"' sbagliato od giusto??
3.Perch il metodo viene dichiarato qui, ma viene 'costruito' nel file cpp, che richiama appunto tale file 'header'
4.fare tutto nel cpp??no??

grazie mille, Zorz

P.S.Appena avr capito 'dove' sono sentirete la mia mancanza..ma ora sopportatemni..grazie:quipy:

Level
14-09-2002, 11:02
Originariamente inviato da zorz
DOMANDINE:
1.Cos' un file 'header'??

Un file che contiene funzioni di libreria predefinite; ad esempio, se in C usi la funzione printf() devi includere nel tuo file l'header stdio.h (nel tuo caso l'header iostream.h) che contiene appunto l'implementazione di printf. Se usi una funzione matematica con Unix o Linux (non mi ricordo con altri sistemi) includi math.h che contiene queste funzioni


2.Riga 2: 'include "cliente.h"' sbagliato od giusto??

E' giusto, perch un header che hai costruito tu. Per gli altri usi la notazione #include <stdio.h>


3.Perch il metodo viene dichiarato qui, ma viene 'costruito' nel file cpp, che richiama appunto tale file 'header'

Perch ti vuol far vedere un esempio dei file header; potevi anche fare tutto nel cpp, ma definendo una funzione nell'header la puoi richiamare da pi files senza doverla ridefinire.


4.fare tutto nel cpp??no??

Certo che lo puoi fare, ma come detto qui ti vuol far vedere un esempio di utilizzo di un file header costruito da te e poi richiamato da un file c o cpp.

ciao.

zorz
14-09-2002, 15:31
Prima di tutto grazie mille Level per la chiarezza..se fossero tutti come te..e poi..ok per la costruzione di file header, in modo che la classe possa essere usata in pi file.ccp, ma perch i metodi inclusi nella classe definita nell header sono 'enunciati' nel file ccp e non nell'header stesso?? grazie ancora, Zorz:)

akiross
14-09-2002, 20:02
Ciao,
se nn ti spiace rispondo io a questa domandina...
Innanzi tutto, un consiglio per i file header:
includi tutto il file in direttive del genere:
#ifndef __PLUTO_H__
#define __PLUTO_H__
....
codice
...
#endif

Questo ti permette di evitare inclusioni multiple del file header. E' buona norma usarlo.
usare __NOME_ESTENSIONE__ e' una mia convenzione, se vuoi, io ho imparato a fare coi' e mi sembra comoda.

Ora passo alla tua domanda:
in genete, negli header, viene messo tutto quel codice che non crea variabili: cioe' le dichiarazioni (di classi, di funzioni, variabili externe eccetera)
questo perche':
se tu metti delle variabili in un file header, nel moneto in cui compili 2 (o +) file cpp che includono il file header, il linker ti dara' un errore.
Ora, e tu crei un file h, ci crei dentro una varaibile, poi includi quell'header in un SINGOLO file CPP, allora nessun problema. Nel momento in cui includi quel file H in piu' file CPP, il compilatore, quando compila i file CPP, si trova 2 o piu' variabili IDENTICHE. Nel momento in cui i file vengono compilati in file oggetto, ok, nessun problema. Quando invece entra in azione il Linker, si trova a dover linkare UNA delle 2 variabili che sono state dichiarate. E dato che il linke e' preciso, non ne prende una a caso, ma i ferma e da un errore.

Questa e' la spiegazione del perche' tutto non si mette nel file CPP o tutto nell'H.
E inoltre, e' piu' comodo poter usare le stesse funzioni in diverse parti di un programma, che se complesso, non dovrebbe essere sviluppato in un singolo file.

LA SINTESI DI TUTTO QUESTO E':
Nei file Headrer ci va TUTTO CIO' CHE NON PRODUCE VARIABILI. Quindi SOLO definizioni.

Capito??
ciao

zorz
14-09-2002, 20:23
:confused:
ciao akiross e grazie per i tuoi puntuali interventi..dunque:

1.non ho conosco la sintassi '#ifndef ' e '#endif'..perch <<..ti permette di evitare inclusioni multiple del file header.>>??cosa intendi??

2.mi rispieghi questo fatto:<<se tu metti delle variabili in un file header, nel moneto in cui compili 2 (o +) file cpp che includono il file header, il linker ti dara' un errore.>>..io chiedevo perch il metodo viene dichiarato nell cpp..che c'entra?? insomma se usa la classe inclusa nell header in pi ccp devo riscrivere per ogni cpp i vari metodi..ex:

#include <iostream.h>
include "cliente.h"

void Cliente::inserisci_nome( )
{
cout << Inserire il nome del dipendente: ";
cin >> nome;
cout << endl;
}

3.<<Nel momento in cui i file vengono compilati in file oggetto, ok, nessun problema. Quando invece entra in azione il Linker, si trova a dover linkare UNA delle 2 variabili che sono state dichiarate.>>..dunque..che cos' il LINKER e la storia delle due variabili..??

grazie per la pazienza.. spero di superare questa fase in cui tutto misterioso, ciao Zorz

Level
14-09-2002, 23:42
Originariamente inviato da zorz
1.non ho conosco la sintassi '#ifndef ' e '#endif'..perch <<..ti permette di evitare inclusioni multiple del file header.>>??cosa intendi??

Ti permette di evitare inclusioni multiple perch se hai gi incluso un file (o hai gi definito ad esempio una costante), il codice compreso tra #ifndef (che sta per: se non definito) e #endif, non viene eseguito. Si usa spesso per definire le macro (costanti).
Esempio:
#ifndef TRUE (se TRUE non stato definito....)
#define TRUE 1 (definisci/poni TRUE = 1)
#endif

Se TRUE aveva gi un altro valore, non assumer valore 1, perch la parte #define TRUE 1 non verr eseguita. In C e in C++ convenzione usare delle macro (definite con #define) al posto di valori numerici (TRUE al posto di 1).



3.<<Nel momento in cui i file vengono compilati in file oggetto, ok, nessun problema. Quando invece entra in azione il Linker, si trova a dover linkare UNA delle 2 variabili che sono state dichiarate.>>..dunque..che cos' il LINKER e la storia delle due variabili..??

Come hai visto, in C e C++ vengono messi insieme file sorgenti (.c o .cpp) in cui tu metti il tuo codice, assieme a file header che contengono funzioni di libreria predefinite, oppure, file header in cui tu stesso hai definito del codice. Il processo che combina il file oggetto prodotto dal tuo sorgente e i file header per arrivare a generare un file eseguibile chiamato linking, cio eseguito da un programma chiamato linker. Come ti ha detto akiross se definisci delle variabili in un header rischi di richiamare una variabile con lo stesso nome pi volte, succede che il linker vede due variabili uguali, non capisce cosa deve fare e si ferma.

ciao.

r0x
15-09-2002, 16:17
zorz:

Cmq:



include "cliente.h"


E` sintatticamente sbagliato. Devi mettere il #:



#include "cliente.h"


La differenza inoltre fra "" e <> e` che con "" la directory di ricerca e` la directory del file che compie l`inclusione; con <> invece ci si riferisce prima alle directory in cui si trovano gli headers di default, che sono definite nelle opzioni del compilatore (ovviamente modificabili).

Schemino sul preprocessore:

#if = "se (analogo ad if)"
#else = "altrimenti (analogo ad else)"
#elif = "se altrimenti (analogo ad else if)"
#ifdef = "se il simbolo e` definito"
#ifndef = "se il simbolo non e` definito"
defined( simbolo ) = restituisce vero/falso se il simbolo e` o non e` definito
#endif = chiude il blocco #if, #ifdef o #ifndef piu` interno
#define = definisce un simbolo
#undef = rimuove un simbolo
#include = sostituisce alla riga l`intero file incluso
#pragma = definisce opzioni specifiche del compilatore

Queste sono le istruzioni piu` comuni. Sono tutti comandi processati prima della compilazione del file. Con tali istruzioni potrai eseguire compilazioni condizionali. Facciamo un esempio:



#define ENGLISH

int main( int argc, char* argv[] )
{
#if defined( ITALIANO )
printf( "Ciao Mondo!\n" );
#elif defined( ENGLISH )
printf( "Hello World!\n" );
#endif
}

// Naturalmente verra` compilato un programma che stampa "Hello World!"


E` una cosa stupida ma dovrebbe rendere l`idea di compilazione condizionale. :)

Questo e` invece uno schema generale su come le parti di un programma andrebbero inserite nei files per non avere problemi di compilazione e/o di linking:

HEADERS (.h, .hpp):
- prototipi;
- classi e strutture (dichiarazioni);
- direttive `extern`;
- macro.

SORGENTI (.c, .cpp):
- variabili (definizioni);
- classi e strutture (definizioni, cioe` i corpi delle funzioni e dei metodi e le inizializzazioni dei membri `static`);

Attenzione! Non definire MAI una variabile in un header (a dispetto di quanto detto), ma solo riferimenti `extern` ad essa in modo da vederla in altri sorgenti. Le variabili vanno definite nei SORGENTI! E questo per un motivo ben preciso.

Esempio:

Metti caso dichiari `int numero;` in un header "file.h". Ora crei un file "file1.c", includi l`header suddetto e compili il file, ed avrai un`istanza di `numero` in "file1.o" (o .obj); poi crei un altro file "file2.c", che fa la stessa identica cosa, in modo da avere un`altra istanza di `numero` in "file2.o" (ma non la stessa!). Ora linki i due files: CASINO!
La soluzione e` dichiarare nell`header solo ed esclusivamente `extern int numero;`, e definire la variabile solo in UNO dei due files .c. A quel punto la variabile sara` una sola e sara` comune ad entrambi i files.

Ciao.

akiross
15-09-2002, 21:46
direi che non c' bisogno di ripondere no?
mi sembra che Level abbia detto tutto giusto...
pero', devo fare una piccola precisazione su cio' che ha detto r0x.
LE DIRETTIVE apl preprocessore, agiscono solo su se stesse, non sul codice C.
Cioe', se fai
#define PIPPO 5
#if PIPPO == 5
printf(...);
#else
printf(...);
#endif

e' corretto, non posso interagice con varibili di c, come in questo caso:

int pippo = 5;

#if pippo == 5
...
#else
...
#endif

inoltre, ti consiglio di usare
#ifdef MACRO

piuttosto che
#if defined(MACRO)

perche' questo ultimo metodo sta andando in disuso, cmq non cambia nulla
/* sapevi che le costanti definite con #define si chiamano MACRO, poi t dico il perche'*/
quersto caso e' sbagliato

Allora, ti spiego le MACRO
Spesso, vengono usate SOLO ed esclusivamente come costanti.
effettivamente, la direttiva DEFINE, non definisce una costante, ma indica al preprocessore che QUALSIASI occorenza della macro che tu hai definito, venga sostituita con un certo testo:

#define PIPPO "Pippo e' andato a mercato con Topolino"

Ogni qualvolta il Preprocessore trova PIPPO, lo sostituisce con quella striga specificata DOPO IL PRIMO SPAZIO

la sintassi e' cosi
#define PRIMA_DELLO_SPAZIO DOPO_LO_SPAZIO

ora, ce' un metodo per costruire delle specie di FUNZIONI, funziona cosi'

#define NOME_MACRO(p1,p2) funzione_che_usa_i_parametri(p1,p2)

ad esempio si mettono spesso nelle macro delle mini-funzioni come:
#define DISEGNA_LINEA(x1,y1,x2,y2) FunzioneCheDisegnaUnaLinea(x1,y1,x2,y2)

E si richiama nel codice cos:
DISEGNA_LINEA(1,2,3,4)

semplice e comodo

Ciao

zorz
16-09-2002, 10:26
:eek: che dire..magnifici e gentili..a parte per il fatto che mi chiarite alcune cosa e me ne incasinate altre..urtroppo vengo da linguaggi di programmazione p semplificati..e il mondo della compilazione mi era oscuro..pensate quello del prepocessore..:eek:
comunque..per akiross..la funzione che tu hai definito come una macro..presente..non mi sembra molto differente che definirla come semplice funzione tra l'header e il main..:quipy: stronzata??
poi..ok per le classi che so cosa sono..le strutture..invece..sono la stessa cosa?? infine..esempi di prototipi e direttive 'extern'..non mi sono molto familiari..grazie Zorz:D

Level
16-09-2002, 12:13
Originariamente inviato da zorz
:eek: che dire..magnifici e gentili..a parte per il fatto che mi chiarite alcune cosa e me ne incasinate altre..urtroppo vengo da linguaggi di programmazione p semplificati..e il mondo della compilazione mi era oscuro..pensate quello del prepocessore..:eek:
comunque..per akiross..la funzione che tu hai definito come una macro..presente..non mi sembra molto differente che definirla come semplice funzione tra l'header e il main..:quipy: stronzata??
poi..ok per le classi che so cosa sono..le strutture..invece..sono la stessa cosa?? infine..esempi di prototipi e direttive 'extern'..non mi sono molto familiari..grazie Zorz:D
In C++ anche le strutture possono essere utilizzate per programmare a oggetti. C' una differenza fondamentale: i membri di una classe per default sono privati, quelli di una struttura sono pubblici.
La parola extern viene utilizzata quando dichiari tutte le variabili globali in un file. Poi da un secondo file vuoi accedere a queste variabili, allora le ridefinisci per mettendo davanti la parola extern. In questo modo da questo file puoi accedere a tutte le variabili senza per riservar loro spazio in memoria. E' sempre il linker che risolve il riferimento a queste variabili esterne.
ciao.

Loading