Forumzone Community

Sistemi Operativi e applicazioni => Microsoft Windows e applicazioni => Programmazione => Discussione aperta da: Superbox il 28 Febbraio 2003, 22:52:22

Titolo: c++ e overload di operatori
Inserito da: Superbox il 28 Febbraio 2003, 22:52:22
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 -> ?

Titolo: c++ e overload di operatori
Inserito da: overmind il 28 Febbraio 2003, 23:49:25
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:

Titolo: c++ e overload di operatori
Inserito da: Superbox il 01 Marzo 2003, 12:55:32
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?

Titolo: c++ e overload di operatori
Inserito da: Lexiw il 01 Marzo 2003, 18:44:23
Ma GetCol() restituisce un puntatore??

Titolo: c++ e overload di operatori
Inserito da: Superbox il 01 Marzo 2003, 21:43:00
CitazioneMa GetCol() restituisce un puntatore??

Si.

La sua declaration/implementation è:

COLONNA * GetCol() const {return itsCol};

Titolo: c++ e overload di operatori
Inserito da: overmind il 02 Marzo 2003, 11:24:34
non è che puoi postare qualche fetta di codice in più?

Titolo: c++ e overload di operatori
Inserito da: Superbox il 02 Marzo 2003, 12:34:57
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... :(

Titolo: c++ e overload di operatori
Inserito da: overmind il 02 Marzo 2003, 12:52:22
Citazione.. il discorso delle tabulazioni, che andando perse renderebbero il codice molto pi� difficile da leggere... :(

prova col pulsante # nel formato testo!

Titolo: c++ e overload di operatori
Inserito da: Superbox il 02 Marzo 2003, 13:43:13
Citazioneprova col pulsante # nel formato testo!

Ehm... non credo di aver capito... :o

Titolo: c++ e overload di operatori
Inserito da: Superbox il 02 Marzo 2003, 13:52:57
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

}
 


Titolo: c++ e overload di operatori
Inserito da: Lexiw il 02 Marzo 2003, 14:46:04
ma se itsCol è di tipo COLONNA come fai a restituirlo in una funzione di tipo NODO?

Titolo: c++ e overload di operatori
Inserito da: Superbox il 03 Marzo 2003, 17:58:55
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)

Titolo: c++ e overload di operatori
Inserito da: Lexiw il 03 Marzo 2003, 18:51:43
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).


Titolo: c++ e overload di operatori
Inserito da: Superbox il 04 Marzo 2003, 13:09:25
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! ;)