|
| HOMEPAGE | INDICE FORUM | REGOLAMENTO | ::. | NEI PREFERITI | .:: | RSS Forum | RSS News | NEWS web | NEWS software | |
| PUBBLICITA' | | | ARTICOLI | WIN XP | VISTA | WIN 7 | REGISTRI | SOFTWARE | MANUALI | RECENSIONI | LINUX | HUMOR | HARDWARE | DOWNLOAD | | | CERCA nel FORUM » | |
![]() |
#1 |
Newbie
Registrato: 24-08-2009
Messaggi: 4
![]() |
[C++]funzionamento costruttori di copia
Sono nuova sia su questo forum che nel campo della programmazione ![]() Volevo riportare qui di seguito una parte del progetto che sto compilando per l'università e chiedere qualche chiarimento che non è mai arrivato da parte del docente. Codice:
#include<iostream> #include<cstdlib> #include<cstring> using namespace std; class indirizzo { char via[30]; char numcivico[10]; int cap; char citta[30]; public: indirizzo(); ~indirizzo(); void put_via(char *s) {strcpy(via,s);} void get_via() {cout<<via<<'\n';} void put_numcivico (char *p) {strcpy(numcivico,p);} void get_numcivico() {cout<<numcivico<<'\n';} void put_cap(int n) {cap=n;} void get_cap() {cout<<cap<<'\n';} void put_citta(char *q) {strcpy(citta,q);} void get_citta() {cout<<citta<<'\n';} }; class CasaEditrice:public indirizzo { char *nome; char *numtel; char *numfax; char *piva; char *id; public: friend ostream &operator<<(ostream &stream, CasaEditrice &CasaEdi); friend istream &operator>>(istream &stream, CasaEditrice &CasaEdi); CasaEditrice(int p); CasaEditrice::CasaEditrice(const CasaEditrice &casaed); ~CasaEditrice(); void put_nome(char *n) {nome=new char[strlen(n)+1]; strcpy(nome,n);} void get_nome() {cout<<nome<<'\n';} void put_numtel(char *n1) {numtel= new char[strlen(n1) +1]; strcpy(numtel,n1);} void get_numtel() {cout<<numtel<<'\n';} void put_numfax (char *n2) { numfax= new char[strlen(n2)+1];strcpy(numfax,n2);} void get_numfax() {cout<<numfax<<'\n';} void put_piva(char *n3) {piva= new char[strlen(n3) +1];strcpy(piva,n3);} void get_piva() {cout<<piva<<'\n';} void put_id(char *n4) {id= new char[strlen(n4) +1];strcpy(piva,n4);} void get_iva() {cout<<piva<<'\n';} }; indirizzo::indirizzo() { via[30]='\0'; numcivico[10]='\0'; cap=0; citta[30]='\0'; } indirizzo::~indirizzo() { if(via) delete[] via; if(numcivico) delete [] numcivico; if(citta) delete[] citta; } CasaEditrice::CasaEditrice(int p) { nome=new char[p]; numtel= new char[p]; numfax= new char[p]; piva= new char[p]; id= new char[p]; if((!nome)&&(!numtel)&&(!numfax)&&(!piva)&&(!id)) { cout<<"impossibile allocare"; exit(1); } *numtel=p; *numfax=p; *piva=p; *id=p; } CasaEditrice::CasaEditrice(const CasaEditrice &casaed) { nome=new char; numtel= new char; numfax= new char; piva= new char; id= new char; if((!nome)&&(!numtel)&&(!numfax)&&(!piva)&&(!id)) { cout<<"impossibile allocare"; exit(1); } *nome=*casaed.nome; *numtel=*casaed.numtel; *numfax=*casaed.numfax; *piva=*casaed.piva; *id=*casaed.id; } CasaEditrice::~CasaEditrice() { if(nome) delete[] nome; if(numtel) delete[] numtel; if(numfax) delete[] numfax; if(piva) delete[] piva; if (id) delete[] id; } ostream &operator<<(ostream &stream, CasaEditrice &CasaEdi ) { stream << CasaEdi.nome << ". "; stream << CasaEdi.numtel << ". "; stream << CasaEdi.numfax << ". "; stream << CasaEdi.piva << ". "; stream << CasaEdi.id << "\n"; return stream; } istream &operator>>(istream &stream, CasaEditrice &CasaEdi ) { cout << "Inserire il nome: "; stream >> CasaEdi.nome; cout << "Inserire num. di tel: "; stream >> CasaEdi.numtel; cout << "Inserire num. di fax: "; stream >> CasaEdi.numfax; cout << "Inserire p.iva: "; stream >> CasaEdi.piva; cout << "Inserire id: "; stream >> CasaEdi.id; return stream; } int main() { CasaEditrice bitti(45) ; cin>>bitti; cout<<Array; bitti.put_via("via alfieri 18"); bitti.get_via(); system ("PAUSE"); return 0 ; } poi, dal manuale, ho appreso che la deallocazione di un array statico non ha bisogno di istruzioni, quindi mi chiedevo se fosse corretto eliminare il distruttore per la classe indirizzo che utilizza l'istruzione delete[] per array di dimensione predefinita. Vi sarei molto grati se mi chiarisse qualcosa soprattutto sui costruttori per array dinamici. Scusate per la poca chiarezza del codice, ma, come ho già detto, la programmazione è cosa nuovissima per me. Grazie a tutti ![]() |
![]() |
![]() |
![]() |
#2 |
Gold Member
WT Expert
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.505
![]() ![]() ![]() |
Sei sicura che il costruttore di copia non faccia riferimento attraverso l'utilizzo di puntatore ad un array statico che viene riallocato con l'operatore new per aumentarne dinamicamente le dimensioni in base all'input dell'utente ?
Se è così, è più che giusto a parer mio l'utilizzo di delete [] nel destructor per lberare la memoria allocata nel constructor dalla classe che eredita indirizzo ps: interessante l'utilizzo degli streams per effettuare gli input (Y) Ultima modifica di LoryOne : 24-08-2009 alle ore 18.40.18 |
![]() |
![]() |
![]() |
#3 |
Newbie
Registrato: 24-08-2009
Messaggi: 8
![]() |
Si, anche io ho dei problemi sullo stesso ( l'ho preso dal prof dell'uni ) però sono molto più indietro di te
Qualcuno potrebbe darmi una mano? Mi imbroglio di brutto |
![]() |
![]() |
![]() |
#4 |
Gold Member
WT Expert
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.505
![]() ![]() ![]() |
T'imbrogli perchè non hai le idee chiare o perchè il prof è un confusionario: Magari butta giu codice in maniera meccanica ... Eleganza ed efficenza di C++ sono fondamentali.
Impara gradualmente, scrivi codice semplice e compilalo. Impara le regole del linguaggio ed attieniti ad esse scrupolosamente ... i virtuosismi lasciali ai boriosi; certe finezze le imparerai col tempo. |
![]() |
![]() |
![]() |
#5 |
Newbie
Registrato: 24-08-2009
Messaggi: 8
![]() |
Va bene, grazie mille
![]() Se per te va bene dare un'occhiata ogni tanto, butto giù il codice di volta in volta e lo incollo nel forum va bene? |
![]() |
![]() |
![]() |
#6 |
Gold Member
WT Expert
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.505
![]() ![]() ![]() |
Per me va benissimo, ho pure 4 occhi
![]() Scherzi a parte, qui troverai tanti utenti con grande esperienza dai quali potrai attingere informazioni e risposte ai tuoi quesiti. ![]() |
![]() |
![]() |
![]() |
#7 |
Newbie
Registrato: 24-08-2009
Messaggi: 4
![]() |
Grazie mille per la disponibilità LaryOne!
![]() ora mi sono accorta che nel main passando un argomento alla funzione bitti.put_indirizzo definendo un puntatore e non passando direttamente la stringa, si blocca l'esecuzione del programma anche se il compilatore compila il codice. Mah scopro sempre più errori. Questa è la mmodifica apportata: Codice:
int main() { CasaEditrice bitti(30); cin>>bitti; cout<<bitti; char *s; cout<<"inserire via"; gets(s); bitti.put_via(s); bitti.get_via(); system ("PAUSE"); return 0 ; } |
![]() |
![]() |
![]() |
#8 |
Gold Member
WT Expert
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.505
![]() ![]() ![]() |
Un po di ripasso
Codice semplice per i semplici concetti fondamentali... Codice:
class MyClass { /* val e copynumber sono due variabili private all'interno della classe. Infatti precedono publlc: Per accedere ai valori dall'esterno è necessario dichiarare una funzione pubblica che ritorni il valore della variabile */ int val; int copynumber; public: /* Costruttore definito direttamente all'interno della classe. E' possibile anche la seguente forma: MyClass::MyClass(int i){ ... ... } Deve essere definita all'esterno della classe, poichè :: indica appartenenza a. Il costruttore di MyClass appartiene alla classe MyClass, ma lo stesso dicasi per le eventuali funzioni i cui soli prototipi sono all'interno della classe, così come per il distruttore */ MyClass(int i) { val = i; copynumber = 0; cout << "Siamo all'interno del normale costruttore\n"; } /* Costruttore di copia Viene definito &o come indirizzo della copia della classe MyClass. Tutte le variabili private del costruttore originario sono accesibili alla copia. val è pari ad i, e copynumber è incrementato di 1 */ MyClass(const MyClass &o) { val = o.val; copynumber = o.copynumber + 1; cout << "Siamo all'interno del costruttore di copia.\n"; cout << "val e' pari a " << o.val << "\n"; } /* Distruttore della classe originaria o del costruttore di copia Due sono le classi: L'originale e la sua copia, quindi 2 volte sarà eseguito il distruttore, ma solo la prima volta copynumber sarà = 0 */ ~MyClass() { if(copynumber == 0) cout << "Distruttore della classe principale.\n"; else cout << "Distruttore del costruttore di copia\n"; } // funzione pubblica che ritorna il valore della variabile privata val int getval() { return val; } }; /* Funzione al di fuori della classe che necessita come parametro la classe stessa, in modo da accedere alla funzione pubblica della classe che mostra il valore della variabile privata val */ void display(MyClass ob) { cout << "Ormai in display val e' pari a " << ob.getval() << '\n'; } int main() { MyClass a(10); display(a); return 0; } Codice:
class MyClass { // a e b sono due varibili private all'interno della classe int a, b; public: MyClass(int i, int j) { a=i; b=j; } friend int comDenom(MyClass x); // La funzione friend }; /* comDenom() non fa parte di nessun membro della classe, ma il suo prototipo è stato creato all'interno della classe per identificare un legame con essa. */ int comDenom(MyClass x) { /* Poichè comDenom() è una funzione friend di MyClass, può accedere direttamente alle variabili private all'interno della classe. Se x.a è < di x.b, allora max = x.a, altrimenti max = x.b */ int max = x.a < x.b ? x.a : x.b; for(int i=2; i <= max; i++) if((x.a%i)==0 && (x.b%i)==0) return i; return 0; } int main() { MyClass n(18, 111); if(comDenom(n)) cout << "Il comune denominatore e' " << comDenom(n) << "\n"; else cout << "Nessun comune denominatore.\n"; return 0; } Io ora vado a letto perchè ho una certa età neh ![]() |
![]() |
![]() |
![]() |
#9 |
Gold Member
WT Expert
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.505
![]() ![]() ![]() |
Classi che ereditano membri di altre classi e possibile violazione di accesso ...
Codice:
class B { // protected: int i, j; // i e j sono due variabili private all'interno di B public: void set(int a, int b) { i = a; j = b; } void show() { cout << i << " " << j << "\n"; } }; class D : public B { // La classe D eredita le funzioni pubbliche da B int k; public: D(int x) { k = x; } void showk() { cout << k << "\n"; } /* Violazione di accesso !!! i è stata dichiarata privata all'interno di B. Per ovviare al problema, si dichiara i protected */ // i = 10; }; int main() { D ob(3); ob.set(1, 2); ob.show(); ob.showk(); return 0; } Ultima modifica di LoryOne : 27-08-2009 alle ore 13.01.10 |
![]() |
![]() |
![]() |
#10 |
Gold Member
WT Expert
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.505
![]() ![]() ![]() |
Operatore new e memoria dinamica
Codice:
main(void){ /* stringa è un array di 6 caratteri. Il sesto carattere è il temrinatore di sequenza, altrimenti noto come terminatore nullo. */ char stringa[]={'1','2','3','4','5','\0'}; /* *p è un puntatore a char e ch è un array statico di 6 elementi. Di ch si conoscono in via preventiva tipologia e dimensione immutabili. *p è un puntatore e di lui si conosce solo la tipologia del dato al quale esso fa riferimento. La locazione in memoria è invece dinamica. */ char *p, ch[6]; // Si copia in ch la sequenza di caratteri di cui si compone stringa strcpy(ch,stringa); cout << ch << "\n"; // Il risultato è la stampa da 1 a 5 escluso '\0' non stampabile /* Attraverso l'operatore new, al puntatore p si assegna la locazione in memoria dinamica di una sequenza di caratteri pari ad 8. */ p = new char[8]; // il primo carattere ha posizione pari a 0 nell'array, l'ultimo 7. /* Alla locazione in memoria ora definita da p si copia la sequenza ottenuta da ch. ch riempie la memoria dinamica fino al sesto carattere, ma gli ulteriori 2 restano disponibili perchè comunque allocati. */ strcpy(p,ch); for(int i=0;i<8;i++) cout << "posizione " << i << " carattere " << p[i] << "\n"; cout << "\n"; /* A questo punto posso decidere quale valore assegnare ai caratteri dell'array al quale punta *p a cominciare dall'ultimo carattere copiato da strcpy. */ p[5]='*'; p[6]='*'; p[7]='*'; for(int i=0;i<8;i++) cout << "posizione " << i << " carattere " << p[i] << "\n"; // Libera la memoria dinamica allocata dal puntatore *p ad array di char delete [] p; } |
![]() |
![]() |
![]() |
#11 |
Newbie
Registrato: 24-08-2009
Messaggi: 8
![]() |
Ciao, scusate se non ho risposto ma non sono molto ferrato e stavo facendo delle prove.
Ora mi trovo nei guai a causa di un intero... mi spiego meglio: Codice:
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> using namespace std; typedef struct VolumeConQuantitaEDisposizione { string nomevol; int quantitadisponibile; string collocazione; }; int main() { VolumeConQuantitaEDisposizione a[5]; string title; string coll; int *quant; for (int i = 0; i < 5; i++) { a[i].nomevol='\0'; a[i].quantitadisponibile='\0'; a[i].collocazione='\0'; cout << i+1 <<": " << a[i].nomevol << " << >> " << a[i].quantitadisponibile << " << >> " << a[i].collocazione<<endl; } for (int i = 0; i < 5; i++) { cout << i+1 <<"° titolo: "; getline(cin,title); a[i].nomevol = title; cout << "Collocazioine: "; getline(cin,coll); a[i].collocazione = coll; cout << "Quantita': "; cin >> *quant; a[i].quantitadisponibile = *quant; } system("PAUSE"); return 0; } L'inizializzazione funziona, ma quando inserisco i dati, dopo l'intero il getline lo salta... come mai?? pensavo di risolvere mettendoci un getline fasullo... che ne dite? |
![]() |
![]() |
![]() |
#12 | |
Guest
Messaggi: n/a
|
Quota:
1. Dovresti evitare di fare così a[i].quantitadisponibile='\0'; anche se è numericamente corretto (e funziona), non è altrettanto semanticamente siccome '\0' è da interpretarsi come un carattere non un intero. perciò è meglio (anche per chi legge il codice fare) a[i].quantitadisponibile=0 2. Per il problema della getline è semplice. Dipende dal sistema operativo su cui lo stai facendo girare. Per inviare i dati premi Invio, no? In Linux, invio è interpretato '\n', Mac OS X usa '\r' e Windows usa "\r\n". Questo cosa significa? Una volta fatta la prima getline, la funzione esce perchè ha incontrato '\r', ma nel buffer rimane l'altro terminatore che è '\n'. Perciò devi svuotarlo. O fai la getline a vuoto o più elegantemente, usa fflush(stdin) appena dopo ogni getline che svuota il buffer. |
|
![]() |
![]() |
#13 |
Newbie
Registrato: 24-08-2009
Messaggi: 8
![]() |
Grazie mille ^_^ , allora metto '\0' per le stringhe ed 0 per gli interi. Ora invece fa una cosa alquanto strana ( tanto per cambiare diciamo ).
Codice:
void Biblioteca::Aggiungi_volume(int quant,string titolo,string coll,int Q) { int i; int j; bool t=false; i=TrovaVolumeDaNome(titolo,Q); if ( i = -1 ) { for (j=0;j<Q && !t;j++) { if ( a[j].nomevol == '\0') // l'errore lo da qui { a[j].nomevol = titolo; a[j].quantitadisponibile=quant; a[j].collocazione = coll; t=true; } } if (j==Q) cout<<"biblioteca piena.\n"; } else a[i].quantitadisponibile=(a[i].quantitadisponibile)+quant; } L'errore che mi dà è il seguente: no match for 'operator==' in '(((Biblioteca*)this)->Biblioteca::a + (+(((unsigned int)j) * 12u)))->VolumeConQuantitaEDisposizione::nomevol == '\000''. E lo trovo strano perchè il simbolo == l'ho usato in un'altra funzione e non mi dà problemi ... ecco il codice della funzione: Codice:
int Biblioteca::TrovaVolumeDaNome (string titolo,int Q) { for (int i=0;i<Q;i++) if (a[i].nomevol == titolo) return i; else return -1; } |
![]() |
![]() |
![]() |
#14 |
Gold Member
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
![]() |
L'operatore '==' è di tipo binario, è sbagliato utilizzarlo con le stringhe per i confronti, può essere molto pericoloso e crearti anche comportamenti inattesi utilizza
string::compare(...) Nel secondo caso ti funziona perché viene calcolata la risultante binaria tra le due espressioni (ma non è comunque consigliabile usarlo), nell'altro caso non funziona perché '\0' è un carattere e per giunta un carattere speciale. |
![]() |
![]() |
![]() |
#15 |
Guest
Messaggi: n/a
|
prima di tutto dal codice sembra che a[i] l'hai dichiarato globalmente. Prima regola per i buon programmi: non dichiarare mai globalmente qualcosa che non siano costanti o variabili "di servizio". Non farlo, rende difficile la ricerca della variabile nel codice e il suo debug, redendo imprevedibili i programmi. Piuttosto passala come argomento.
Secondo, le stringhe non vanno mai comparate con == ! Questo perché le stringhe le puoi considerare un vettore e nella variabile fittizia string viene salvato l'indirizzo della prima cella. Confrontando con if due variabili string si confronta in realtà il loro indirizzo in memoria, che sarà (sennò colliderebbero) sempre diverso. Il modo giusto per confrontare due stringhe è usare la funzione compare fornita dall'include <string> perciò (ammentendo di seguire c++) if( titolo.compare(a[i].nomevol)==0 ) Terzo, if ( i = -1 ) così fai un assegnamento. Se il tuo obiettivo è confrontare devi fare if (i == -1) Quarto, a[j].nomevol == '\0' così stai confrontando una stringa con un carattere. Se vuoi sapere se la stringa è vuota (credo sia questo il tuo obiettivo) devi verificare il carattere. per me invece di assegnarli '\0' verrebbe più comodo se li inizializzazi le stringhe come "". in questo modo ti basterebbe fare if(a[i].nomevol.empty()) e controlli se la stringa è vuota. |
![]() |
![]() |
Utenti attualmente attivi che stanno leggendo questa discussione: 1 (0 utenti e 1 ospiti) | |
Strumenti discussione | |
|
|
![]() |
||||
Discussione | Autore discussione | Forum | Risposte | Ultimo messaggio |
Masterizzare una copia di back up del s.o. | fisiologohifi | Masterizzazione Giochi Games | 6 | 14-12-2006 16.15.20 |
RIAA: ma quale diritto di copia? | Macao | Segnalazioni Web | 0 | 20-02-2006 00.15.03 |
Copia privata, si può ??? | Macao | Segnalazioni Web | 12 | 15-10-2004 18.17.23 |
Costruttore di copia C++ | GiulioCesare | Programmazione | 8 | 01-07-2004 09.31.25 |
vecchi trucchi ma su xp? | top gun | Windows 7/Vista/XP/ 2003 | 13 | 02-03-2004 10.31.48 |