Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    [c++] virtual, puntatori e vector

    Ciao gente, ho cercato di focalizzare il più possibile un problema che mi si è presentato:
    codice:
    #include <iostream>
    #include <vector>
    using namespace std;
    
    class Materiale {
        public:
            virtual double get_E() {
                return 0.;
            }
    };
    
    class Acciaio : public Materiale {
        double E;
    
        public:
        Acciaio(){
            E=210000.;
        }
    
        double get_E(){
            return E;
        }
    };
    
    /* eventuale altro materiale*/
    /*class Acciaio2 : public Materiale {
        double E;
    
        public:
        Acciaio(){
            E=100000.;
        }
    
        double get_E(){
            return E;
        }
    };
    */
    
    class Nodo {
            Materiale* m;
    
            //inizio costruttori e funzioni
            public:
            Nodo() {
            }
    
            /**/
            Materiale* get_materiale(){
                return m;
            }
            double get_E() {
                return m->get_E();
            }
    
            void set_materiale(Materiale &mat){
                m = &mat;
            }
    };
    
    class Elemento {
            public:
            std::vector<Nodo> nodo;
    
            //inizio costruttori e funzioni
            public:
            Elemento() {
            }
    
            double get_E() {
                double E=0.;
                for(int i=0;i<nodo.size();i++){
                    E=E+nodo[i].get_E();
                }
                return E/nodo.size();
            }
    };
    
    int main()
    {
        std::vector<Acciaio> acciaio;
        std::vector<Elemento> elemento;
    
        elemento.push_back(Elemento());
    
        elemento[0].nodo.push_back(Nodo());
        //elemento[0].nodo.push_back(Nodo()); //commentando questa riga funziona, togliendo il commento non funziona
    
        for(int i=0;i<elemento.size();i++) {
            for(int k=0;k<elemento[i].nodo.size();k++) {
                acciaio.push_back(Acciaio());
                elemento[i].nodo[k].set_materiale(acciaio.back());
            }
        }
    
        for(int i=0;i<elemento.size();i++) {
            for(int k=0;k<elemento[i].nodo.size();k++) {
                std::cout<<elemento[i].nodo[k].get_E()<<"\n";
            }
        }
    
        return 0;
    }
    Perchè se commento la riga il codice funziona e se la decommento non funziona più? Come posso risolvere tale problema volendo avere potenzialemente infiniti elementi con un certo numero di nodi ciascuno alla quale è associato un materiale?
    (e' all'incirca l'ultimo topic da me aperto, ma in versione più concreta e ridotta all'osso, così da dover essere più semplice per qualche esperto rispondere oltre ad essere un caso più semplicemente estensibile. Nel caso fosse ritenuto un messaggio doppio prego il moderatore di chiudere o eliminare l'altro topic)

  2. #2
    Il problema è che ogni volta che tu aggiungi un elemento al vector acciaio, questo può esaurire la sua capacità interna e decidere di riallocare il blocco di memoria che gestisce, rendendo non più validi tutti i puntatori ai suoi elementi. La soluzione più semplice è evitare questi giri strani con i vettori e semplicemente usare dentro Nodo uno smart pointer che gestisca l'oggetto di tipo Materiale. Se non ti serve condividere i medesimi materiali tra più nodi, in C++ pre-11 puoi usare std::auto_ptr (avendo cura di disabilitare il costruttore di copia di Nodo), con l'ultima versione dello standard (o usando Boost) puoi usare unique_ptr/scoped_ptr.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Originariamente inviato da MItaly
    Il problema è che ogni volta che tu aggiungi un elemento al vector acciaio, questo può esaurire la sua capacità interna e decidere di riallocare il blocco di memoria che gestisce, rendendo non più validi tutti i puntatori ai suoi elementi.
    Cosa intendi che può esaurire la sua capacità interna?! Nel codice che ho inserito se decommento la riga in questione si creano 2 oggetti acciaio...
    Originariamente inviato da MItaly
    La soluzione più semplice è evitare questi giri strani con i vettori e semplicemente usare dentro Nodo uno smart pointer che gestisca l'oggetto di tipo Materiale.
    smart-puntatori.....sono qualcosa che esiste (e magari hai qualche link da farmi leggere) o consiste nell'inventarsi qualcosa che li renda "smart"?
    Originariamente inviato da MItaly
    Se non ti serve condividere i medesimi materiali tra più nodi, in C++ pre-11 puoi usare std::auto_ptr (avendo cura di disabilitare il costruttore di copia di Nodo), con l'ultima versione dello standard (o usando Boost) puoi usare unique_ptr/scoped_ptr.
    Questa cosa provo a studiarmela da solo..
    Grazie per risposta!

  4. #4
    Risposta alla domanda 1) : http://forum.html.it/forum/showthrea...3#post12851333

    Alla domanda 2 ...non sò ancora risolvere

    Alla 3..sto cercando di salvare dentro Nodo un elemento unique_ptr ma senza successo
    Ho sempre errori tipo:
    codice:
    error: invalid use of member (did you forget the '&' ?)
    o
    codice:
    deleted function ....

  5. #5
    Posta il codice modificato...
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Avevo pensato di usare lo "smart pointer" dentro Nodo con qualcosa di simile...
    codice:
    class Nodo {
            ...
            std::unique_ptr<Materiale> m; //puntatore fisso
            ...
    };
    o
    codice:
    class Nodo {
            ...
            std::unique_ptr<Materiale> m(); //puntatore fisso
            ...
    };
    ma, con il primo modo non ne vuole sapere di funzionare...

    Con il secondo poi non sò come assegnare al puntatore l'indirizzo dell'oggetto in vector (che ora non dovrebbe più cambiare di indirizzo di memoria con questo tipo di puntatore...)

    codice:
    class Nodo {
            ...
            std::unique_ptr<Materiale> m(NULL); //puntatore fisso
            ...
    };
    con questo ottengo:
    error: expected identifier before '__null'
    error: expected ',' or '...' before '__null'

  7. #7
    È giusto il primo, per impostare un nuovo puntatore da gestire (eliminando al contempo l'oggetto che gestiva in precedenza) chiama il suo metodo reset.
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Originariamente inviato da MItaly
    È giusto il primo, per impostare un nuovo puntatore da gestire (eliminando al contempo l'oggetto che gestiva in precedenza) chiama il suo metodo reset.
    il primo non me lo lascia compilare!!!
    Mi restituisce qualcosa come:

    lib\gcc\mingw32\4.4.1\include\c++\bits\unique_ptr. h|214|error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = Materiale, _Tp_Deleter = std::default_delete<Materiale>]'|

    ecc ecc ecc

  9. #9
    Usando unique_ptr l'oggetto diventa non copiabile; invece di push_back usa emplace_back.
    Amaro C++, il gusto pieno dell'undefined behavior.

  10. #10
    Questo il codice completo:
    codice:
    #include <iostream>
    #include <vector>
    #include <memory>
    using namespace std;
    
    class Materiale {
        public:
            virtual double get_E() {
                return 0.;
            }
    };
    
    class Acciaio : public Materiale {
        double E;
    
        public:
        Acciaio(){
            E=210000.;
        }
    
        double get_E(){
            return E;
        }
    };
    /* eventuale altro materiale*/
    /*class Acciaio2 : public Materiale {
        double E;
    
        public:
        Acciaio(){
            E=100000.;
        }
    
        double get_E(){
            return E;
        }
    };
    */
    
    class Nodo {
            std::unique_ptr<Materiale> mat;
    
            //inizio costruttori e funzioni
            public:
            Nodo() {
            }
    
            /**/
            double get_E() {
                return mat->get_E();
            }
    
            void set_materiale(Materiale &m){
                mat.reset(&m);
            }
    };
    
    class Elemento {
            public:
            std::vector<Nodo> nodo;
    
            //inizio costruttori e funzioni
            public:
            Elemento() {
            }
    
            double get_E() {
                double E=0.;
                for(int i=0;i<nodo.size();i++){
                    E=E+nodo[i].get_E();
                }
                return E/nodo.size();
            }
    };
    
    int main()
    {
    
        std::vector<Elemento> elemento;
        std::vector<Acciaio> acciaio;
    
        elemento.emplace_back(Elemento());
    
        elemento[0].nodo.emplace_back(Nodo());
        elemento[0].nodo.emplace_back(Nodo());
    
        for(int i=0;i<elemento.size();i++) {
            for(int k=0;k<elemento[i].nodo.size();k++) {
                acciaio.emplace_back(Acciaio());
                elemento[i].nodo[k].set_materiale(acciaio[i]);
            }
        }
    
        for(int i=0;i<elemento.size();i++) {
            for(int k=0;k<elemento[i].nodo.size();k++) {
                std::cout<<elemento[i].nodo[k].get_E()<<"\n";
            }
        }
    
        return 0;
    }
    emplace o non emplate, std::unique_ptr<Materiale> mat; o std::unique_ptr<Materiale> mat(NULL); o std::unique_ptr<Materiale> mat();

    non funziona... (fate un rapido copia e incolla per vedere!) ... io proprio non so' più che santi chiamare!
    non ho mai perso tanto tempo dietro a un problema come questa volta...

    Nella realtà è tanto semplice: Tanti oggetti che contengono tanti oggetti che possono collegarsi ad altri oggetti (diversi, la cui classe madre è la classe Materiale).

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.