Salve a tutti, e in bocca al lupo ai mod per questo nuovo interessante forum! :)
Mi sono letto, per ora, i primi 12 giorni del manuale c++ in 21 days, ma chiaramente con la testa sono già avanti e cerco di fare cose che su tale manuale non sono scritte (nemmeno nei capitoli successivi). Dato che imparo meglio (e più in fretta), "giocando" un po' con il codice per i fatti miei... eccomi qui con un bel quesito! ;)
Sparo subito la domanda che mi assilla da mesi: come si fa un overload dell'index operator in c++?
Mi sono inchiodato in quel punto e, dopo qualche giorno di tentativi, sono riuscito a compilare lo stesso. Chiaramente i risultati non sono stati quelli sperati (il prog non fa quello che dovrebbe)... e quindi ho lasciato il mio dsw a sedimentare per settimane...:(
Ora che c'è il forum, spero possiate guidarmi verso la luce! :)
Veniamo al dunque: ecco il passo incriminato (sperando che la mancanza di tabulazioni non lo incasini troppo):
NODO operator[] (int & posizione) const
{
int i;
NODO *temp;
temp = itsNext;
for (i=(posizione-1); i>0; i--)
{
temp=temp->GetNext();
cout<< "Mi sto spostando di 1 nodo..."< }
return temp->itsCol;
}
NODO è chiaramente una classe. In pratica si tratta del mio primo tentativo di creare una lista; l'intento del mio overload è quello di poter passare da un nodo all'altro della lista "alla maniera degli array".
Esempio: pHead[2].GetCol()->GetPar(2)
dove pHead è il primo nodo, e il [2] è il parametro che gli comunica di quanti nodi si deve spostare per trovare quello che mi interessa. Il problema sta nel fatto che questo "accesso" ai nodi non me lo lascia fare.
Che io debba fare un overload anche dell'operatore -> ?
a quest'ora se penso a queste cose mi viene solo in NULL nel cervello.. :D
Vedrò se posso aiutarti, per quanto riguarda l'indentazione chiedo a glide se si possono inserire i
così possiamo indentare :cool:
Ok. Grazie, Overmind. ;)
Faccio solo una precisazione, perchè rileggendo il mio post precedente non mi è sembrato abbastanza chiaro sul mio problema.
L'estratto di codice che ho riportato è sintatticamente valido (il compilatore non dà errori di sorta), quindi l'overload dell'index operator in teoria sono riuscito a farlo. Quel che invece non riesco a fare è utilizzare tale overload in pratica. Insomma, il problema è più nell'esempio che ho fatto che non nella parte di codice riportata. :h
Nell'esempio:
- pHead è il primo nodo della lista (l'unico che mi interessa conoscere, dato che per accedere a quelli successivi voglio usare appunto l'index operator, a cui comunico l'offset X, ottenenendo così uno spostamento al nodo successivo per X volte);
- GetCol è un public accessor della classe NODO e in pratica restituisce l'oggetto "contenuto" nel nodo in questione (oggetto che è un membro della classe COLONNA, che non sto a spiegarvi cos'è per non incasinare di più il discorso);
- GetPar è un public accessor della classe COLONNA.
Il problema è che il metodo da me utilizzato (pHead[2].GetCol()->GetPar(2)) è sintatticamente scorretto, quindi non riesco a compilare. Ho provato altre soluzioni sintattiche, che ora non mi vengono in mente, ma non ho cavato un ragno dal buco. :(
La domanda vera quindi è: secondo voi come faccio ad accedere agli oggetti della mia lista servendomi dell'index operator?
Ho sbagliato l'overload o sto sbagliando il metodo di accesso?
Ma GetCol() restituisce un puntatore??
CitazioneMa GetCol() restituisce un puntatore??
Si.
La sua declaration/implementation è:
COLONNA * GetCol() const {return itsCol};
non è che puoi postare qualche fetta di codice in più?
Citazionenon è che puoi postare qualche fetta di codice in più?
Potrei postarlo tutto (saranno un centinaio di righe, commentate una ad una).
Ma c'è il discorso delle tabulazioni, che andando perse renderebbero il codice molto più difficile da leggere... :(
Citazione.. il discorso delle tabulazioni, che andando perse renderebbero il codice molto pi� difficile da leggere... :(
prova col pulsante # nel formato testo!
Citazioneprova col pulsante # nel formato testo!
Ehm... non credo di aver capito... :o
Forse ho capito.
Ci provo. Vediamo come viene... :)
class COLONNA
{
public:
COLONNA()
{
usint i = 0;
for (i=0; i<13; i++)
{
char defris[] = "1";
par = defris[0];
}
cout<< "colonna costruita"< }
~COLONNA() { cout<< "colonna distrutta"< char GetPar(usint n) const { return par[n]; }
void SetPar(usint n, char ris[2])
{
par[n] = ris[0];
}
private:
char par[13];
};
class NODO
{
public:
NODO(COLONNA*pCol) // COSTRUTTORE DI NODO
{ // la colonna viene passata come parametro
itsCol = pCol; // ad una colonna temporanea di nome itsCol (privata)
itsNext = 0; // e si assegna 0 di default al puntatore al prox nodo
itsLast = 0;
cout<<"E' stata creata una colonna all'indirizzo: "< cout<< "nodo costruito"< }
~NODO() // DISTRUTTORE DI NODO
{ // libera lo spazio occupato nel Free Store
cout<<"Il nodo successivo a questo era in posizione: "<< itsNext< cout<<"La colonna questo nodo era in posizione: "<< itsCol< delete itsCol;
itsCol = 0;
delete itsNext;
itsNext = 0;
itsLast = 0;
cout<< "ma ora è un nodo distrutto"< }
void Insert(NODO * nodoNew) // INSERTER DI NUOVI NODI
{
if (!itsNext) // Se l'itsNext di questo nodo è 0, significa che
{ // questo è già l'ultimo nodo della lista, quindi
itsNext = nodoNew; // il nuovo nodo viene inserito subito dopo
itsLast = nodoNew; // Dopo la creazione del primo nodo dopo l'head,
// questo IF viene ovviamente skippato
cout<< "Questo e' il primo nodo dopo l'head"< cout<< "Il suo indirizzo e': "< }
else // altrimenti si sposta all'ultimo nodo in lista
{ // e inserisce il nuovo nodo dopo di esso
cout<< "Inserisco il nuovo nodo a fondo lista" << endl;
cout<< "Il suo indirizzo e': "< itsLast->SetNext(nodoNew);
itsLast = nodoNew;
// Nel primo nodo, itsLast punta SEMPRE all'ultimo nodo della lista, e serve solo per
// inserire l'indirizzo di nodoNew nell'itsNext dell'ultimo nodo in lista.
// In tutti i nodi "di mezzo" alla lista, invece, itsLast non serve a niente, dato che
// il suo contenuto equivale sempre a quello di itsNext, e per questo è necessario che
// la chiamata Insert sia effettuata SEMPRE E SOLO sul primo nodo (pHead)!!!!!
// In caso contrario, i nuovi nodi creati verrebbero inseriti AGLI STESSI INDIRIZZI
// dei nodi già creati in posizioni successive a quello su cui l'Insert è chiamato!
}
}
void SetNext(NODO * nodo) { itsNext = nodo; } // imposta l'indirizzo del prox nodo
NODO * GetNext() const { return itsNext; } // fornisce l'indirizzo del prox nodo
COLONNA * GetCol() const { return itsCol; } // fornisce la colonna contenuta nel nodo
NODO operator[] (int & posizione) const
{
int i;
NODO *temp;
temp = itsNext;
for (i=(posizione-1); i>0; i--)
{
temp=temp->GetNext();
cout<< "Mi sto spostando di 1 nodo..."< }
return temp->itsCol;
}
private:
COLONNA *itsCol; // contenitore della colonna passata al nodo
NODO *itsNext; // contenitore dell'indirizzo del prox nodo in lista
NODO *itsLast; // contenitore dell'indirizzo dell'ultimo nodo in lista
};
// DIMOSTRAZIONE DEL CORRETTO FUNZIONAMENTO DELLA LISTA
NODO *pNodo = 0; // crea un nodo temporaneo (*Nodo) e lo inizializza
COLONNA *pCol = new COLONNA; // crea una colonna temporanea (*pCol) nel Free Store
int risp;
NODO *pHead = new NODO(pCol); // crea il nodo *pHead in Fstore e gli passa la *pCol;
while (1) // inizio forever loop
{
cout << "Creare un'altra colonna ( numero qualunque = si, 0 = no)? ";
cin >> risp;
if (!risp) break; // se risp è 0, il forever loop termina
pCol = new COLONNA; // crea una nuova colonna in Fstore e la passa per rif a pCol
pNodo = new NODO(pCol); // crea un nodo per contenere pCol e lo passa per rif a pNodo
pHead->Insert(pNodo); // inserisce il nuovo nodo a fondo lista
}
cout<< "Partita 1 Colonna 1: " << (pHead->GetCol())->GetPar(0) << endl;
cout<< "Partita 3 Colonna 1: " << (pHead->GetCol())->GetPar(2) << endl;
cout<< "Assegno 2 alla terza partita..."<< endl;
(pHead->GetCol())->SetPar(2, "2" ;);
//pHead[2].GetCol()->SetPar(2, "2" ;);
//cout<< "Partita 3 Colonna 1: " << pHead[2].GetCol()->GetPar(2) << endl;
cout<< "Partita 3 Colonna 1: " << pHead->GetCol()->GetPar(2) << endl;
// PROBLEMA: L'OPERATORE [] NON SI SA COME E SE FUNZIONA!!!
delete pHead;
cout << "Funziona?"<
// DIMOSTRAZIONE DEL CORRETTO FUNZIONAMENTO DELLA CLASSE COLONNA
/* COLONNA integrale[2];
cout < cout << "Tredicesima partita colonna 1: " << integrale[0].GetPar(12) << endl;
cout << "Terza partita colonna 1: " << integrale[0].GetPar(2) << endl;
cout << "Assegno 2 alla terza partita..."<< endl;
integrale[0].SetPar(2, "2" ;);
cout << "Terza partita colonna 1: " << integrale[0].GetPar(2) << endl;
cout < cout << "Tredicesima partita colonna 2: " << integrale[1].GetPar(12) << endl;
cout << "Terza partita colonna 2: " << integrale[1].GetPar(2) << endl;
cout << "Assegno X alla terza partita: "<< endl;
integrale[1].SetPar(2, "X" ;);
cout << "Terza partita colonna 2: " << integrale[1].GetPar(2) << endl;
cout < cout << "Tredicesima partita colonna 1: " << integrale[0].GetPar(12) << endl;
cout << "Terza partita colonna 1: " << integrale[0].GetPar(2) << endl;
*/
//FINE DIMOSTRAZIONE
}
ma se itsCol è di tipo COLONNA come fai a restituirlo in una funzione di tipo NODO?
Citazionema se itsCol è di tipo COLONNA come fai a restituirlo in una funzione di tipo NODO?
Quindi vuoi dire che mi basterebbe sostituire
NODO operator[] (int & posizione) const
con
COLONNA operator[] (int & posizione) const
per far quadrare tutto?
(non ho ancora reinstallato Visual Studio... per quello te lo chiedo... :o :h)
Si ma dopo devi usarla nel seguente modo pHead[2]->GetPar(2),
Comunque per coerenza dovresti modificare la funzione e fargli ritornare *temp e usare l'operatore come hai indicato:
pHead[2].GetCol()->GetPar(2).
CitazioneSi ma dopo devi usarla nel seguente modo pHead[2]->GetPar(2),
Comunque per coerenza dovresti modificare la funzione e fargli ritornare *temp e usare l'operatore come hai indicato:
pHead[2].GetCol()->GetPar(2).
Infatti prediligo la secondo ipotesi.
Facendogli ritornare tutto l'oggetto *temp, invece che la sua locazione di memoria, sembra avermi risolto definitivamente il problema.
L'overload quindi è esatto... vero? :o :h
Grazie mille x l'aiuto! ;)