Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Eseguire Cast
Forum - C/C++ - Eseguire Cast

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 11:44
Mercoledì, 26/12/2018
Buongiorno a tutti e buon Santo stefano.

Stavo cercando di convertire una struttura con campi uguali da una classe ad un'altra
ma ho questo errore.

Sò che sicuramente sbaglio completamente tutto. per questo voglio chiedervi come posso eseguire correttamente il cast.
e una volta per tutte imparare a farlo.

ho 2 classi


Classe 1  MappySaver  ( Utilizza per scrivere file di salvataggio in binario)

Codice sorgente - presumibilmente C++

  1. class MappySaver
  2. {
  3.  
  4. public:
  5.  
  6.  
  7.     MappySaver();
  8.     void SaveMap(QString filename);
  9.  
  10.     //structure
  11.     struct Tile
  12.     {
  13.     public:
  14.         int ID;
  15.         int x,y,w,h;
  16.         QRect rect;
  17.     };
  18.  
  19.     QList<Tile> Tiles;
  20.     QObject t;
  21.     Tile tile;
  22.  
  23. };




Classe Jexport utilizzata per esportare in Json un livello

Codice sorgente - presumibilmente C++

  1. class Jexport
  2. {
  3.  
  4. public:
  5.     Jexport();
  6.  
  7.     int MappyVer;
  8.  
  9.     //Save Method
  10.     void Read(const QJsonObject &obj);
  11.     void Write(QJsonObject &obj) const;
  12.  
  13.  
  14.     //structure
  15.     struct Tile
  16.     {
  17.     public:
  18.         int ID;
  19.         int x,y,w,h;
  20.         QRect rect;
  21.     };
  22.  
  23.     QList<Tile> Tiles;
  24.  
  25. };
  26.  
  27. #endif // JEXPORT_H




Entrambi le classi hanno la stessa struttura e la stessa lista con lo stesso nome.

ho provato a fare in questo modo

Codice sorgente - presumibilmente Plain Text

  1. MappySaver m; //Classe MappySaver
  2.     MappySaver::Tile tile; //Struttura
  3.  
  4.     tile.ID = 0; //elemento di test
  5.  
  6.     m.Tiles.append(tile);
  7.  
  8.     //Tentativo di portare la lista m.Tiles a quella Json
  9.  
  10.     Jexport j;
  11.  
  12.  
  13.     j.Tiles = static_cast<QList<Jexport::Tile>>(m.Tiles);




Ora sò che sicuramente ho fatto un macello o sbagliato completamente tutto.
Come posso fare ciò?

Ovvero prendere direttamente una lista basata su struttura e riportarla tale com'è iin u'altra classe?



errore
/home/giovanni/cpp/Mappy/mainwindow.cpp:412: error: no matching conversion for static_cast from 'QList<MappySaver::Tile>' to 'QList<Jexport::Tile>'
    j.Tiles = static_cast<QList<Jexport::Tile>>(m.Tiles);
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 14:03
Mercoledì, 26/12/2018
Ciao, l'errore è banale, l'operatore di cast per i tipi base è gia definito, nel tuo caso non hai niente di gia pronto, dovresti ridefinire l'operatore di cast(nota dall'errore che per lui i due Tile non sono la medesima cosa perche definiti in luogi differenti). Ma prima di mettere le mani su questo caso specifico potresti spiegarmi il tuo obbiettivo finale, perche se ho intuito bene questo non mi pare un buon modo per raggiungerlo.

Ultima modifica effettuata da Roby94 il 26/12/2018 alle 14:05
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 23:27
Mercoledì, 26/12/2018
Il.fatto è che le due strutture, anche se sono uguali a livello di cosoce non c'entrano nulla l'una con l'altra.

Una si chiama MappySaver::Tipe e l'altra Jexprot::Tile.

Come ti ho già detto tu non sai a priori come il compilatore organizzerà in memoria i campi di una struttura e questo induce l'errore che hai sperimentato: il compilatore si rifiuta di fare il cast di due strutture uguali.

Ora tu ti trovi davanti a due scelte: usare una struttura comune a tutte le classi di salvataggio, magari una struttura che sia definita allinterno di una classe base (magari astratta) che definisce l'interfaccia di salvataggio, oppure definire un cast dall'una verso l'altra. È ovvio che la secomda scelta implica maggior lavoro e riduce la mantenibilita fitura: se mai dovessi aggiungere una ulteriore struttura identica ti ritroveresti a dover definire un cast per ogni vecchia struttura a quella nuova, e un cast mella nuova struttura epr ognuna di quelle vecchie (nel caso peggiore).

Probabilmente non stai seguendo un approccio corretto e come ben dice Roby94 dovresti darci l'idea di ciò che vuoi ottenere, così possiamo indirizzarti verso un modello logico migliore o/e più mantenibile.

Magari potresti spiegarci la necessità di ridefinire una struttura identica (cosa che stavo per dare per scontata, ma che non lo è affato) che ragionamento c'è dietro?

PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 11:32
Giovedì, 27/12/2018
Si avete ragione.
Cerco di spiegare cosa intendo fare.

Quello che cerco di fare è avere una struttura ed una lista base dove poter trasferire i dati al suo interno in determinate classi differenti.
Ad esempio:

Poniamo di avere una carta di identità dove abbiamo nome, cognome, indirizzo ecc. ecc.

Questa carta di identità può trasferire i suoi valori ad esempio a Roby94 o a DarkJuster questo dipende dalla situazione attuale.
Ovviamente i dati possono cambiare, ora mi posso chiamare Thejuster e dopo solo Juster ma la carta è quella.


La classe base è quella definita in MappySaver::Tile che sarebbe una struttura rilegata ad una lista che contiene tutti gli elementi del disegno attuale.


Tramite la classe MappySaver con opportuni override degli operatori, serializzo in binario il contenuto della lista.
Mentre tramite la classe JExport::Tile  deve serializzare in formato JSON per poter rendere leggibile il contenuto da un browser web o altro.

Ho ritenuto dunque dare come nome MappySaver proprio per definire questa classe come un trampolino.
che sia in grado di indirizzare i suoi dati in classi differenti.

Certo, potrei usare un semplice ciclo for, ma dovrei ricopiare i dati ogni volta.

Quello che intendevo fare, e in un colpo solo trasferire tutta la Lista<Tile>  in altre classi.
Quindi credevo di poter forzare il compilatore tramite un Cast ad identificare che i dati che gli stavo passando erano uguali alla sua lista e quindi inserirli. ma ho appunto un errore che mi impedisce di farlo.

Non sò. Mi consigliate di creare una semplice classe con Lista e struttura ed includerla in entrambi i file?
O esiste un modo per fare quello che ho scritto sopra?



https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 14:01
Giovedì, 27/12/2018
Se la questione è solo serializzare (i dati della classe JExport sono in sola lettura) non ha senso ricopiarsi tutti i dati in una nuova parte di memoria, ha invece senso referenziare i dati da un altra parte, come fare questo è una scelta che sta a te. Potresti come consiglia  TheDarkJuster creare una classe base astratta base ad entrambe e eseguire un cast build-in che il compilatore è molto bravo a gestire e solitamente non implica spostamento di dati, oppure potresti creare la classe JExport come figlia della classe MappySaver che aggiunge i metodi per l'esportazione in JSON e anche in questo caso il cast è definito implicitamente (nessuno spostamento di memoria). Un altro metodo ancora, crei una struttura esterna (classe o struct indifferente) e all'interno delle due classi ti crei un shared pointer che puntano ad una sua istanza, in questo modo fai pure un uso intelligente di uno smart pointer che quando entrambe le classi verranno distrutte de allocherà in automatico l'istanza della struttura.  Oppure puoi implementare i metodi per l'esportazione json gia nella classe MappySaver, ma se non l'hai gia fatto ci saranno dei buoni motivi.

PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 12:02
Domenica, 30/12/2018
Eccomi scusate per la risposta in ritardo.
In realtà volevo rendere le cose più dinamiche separandole in classi diverse ma ho capito che non va bene avere più classi per la serializzazione.
Più che altro era per facilitare in seguito la lettura dei file da altri programmi esterni.

Comunque userò il metodo che mi avete consigliato che sicuramente funzionerà senza problemi.

Inserirò l'esportazione del JSON direttamente nella classe Mappy Saver anziché creare una classe separata solo per il JSON.

Come sempre grazie mille dell'aiuto e dei vostri preziosi consigli.


https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 21:52
Domenica, 30/12/2018
Testo quotato

Postato originariamente da Thejuster:

Eccomi scusate per la risposta in ritardo.
In realtà volevo rendere le cose più dinamiche separandole in classi diverse ma ho capito che non va bene avere più classi per la serializzazione.
Più che altro era per facilitare in seguito la lettura dei file da altri programmi esterni.

Comunque userò il metodo che mi avete consigliato che sicuramente funzionerà senza problemi.

Inserirò l'esportazione del JSON direttamente nella classe Mappy Saver anziché creare una classe separata solo per il JSON.

Come sempre grazie mille dell'aiuto e dei vostri preziosi consigli.



Io credo che tu mi abbia frainteso: va benissimo creare una classe InterfacciaSerializzazione che definisce un metodo salva() e poi da questa ereditare SerializzatoreJSON e SerializzatoreXML ciò che non va bene è definire due strutture uguali e aspettarsi che sia lecito poter fare il cast dall'una all'altra, visto chè è una operazione dubbia anche dal punto di vista organizzativo. Se hai bisogno di utilizzare la struttura nei vari serializzatori, e questa è definita altrovew basta disegnare salva() in maniera tale che accetti come parametro d'ingresso un riferimento costante alla struttura.

PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 12:51
Giovedì, 10/01/2019
Riprendendo un attimo il discorso di Roby.
Come posso ridefinire un cast?

Magari qualche piccolo esempio.

Il tutto è sempre ed unicamente a scopo didattico. Sto cercando di imparare questo linguaggio perché mi affascina moltissimo.


https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 19:01
Giovedì, 10/01/2019
Testo quotato

Postato originariamente da Thejuster:
Riprendendo un attimo il discorso di Roby.
Come posso ridefinire un cast?

Magari qualche piccolo esempio.

Il tutto è sempre ed unicamente a scopo didattico. Sto cercando di imparare questo linguaggio perché mi affascina moltissimo.


opertator <tipodiritorno>() const;

Poi fai uno static_cast<tipodiritorno>(oggettodaconvertire);

PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo