[RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

di il
14 risposte

[RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

Ciao a tutti,
ho un oggetto Iniettore che deriva da una classe astratta Alimentatore che a sua volta deriva da Componente (sempre astratta).
tutte le derivazioni sono pubbliche (subtyping).
Iniettore<Alimentatore<Componente.

L'unica cosa che deve esprimere Iniettore è il fatto che può essere Elettrico, Misto, o Meccanico. Avevo pensato di fare un enumeratore con
queste 3 possibilità e mettere questo tipo enum come unico campo dati di Iniettore.
E adesso sorge il dubbio dove devo mettere l'enum?????
Cioè non so proprio dove collocarlo nella gerarchia. Devo fare una nuovo classe (bho mi sembra assurdo), o devo metterlo nel file main.cpp fuori dalla funzione int main() ????? anche perché dovrei usarlo in tutti i file che usano il tipo Iniettore.

Help

14 Risposte

  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Personalmente metterei l'enum nella classe Alimentatore, in quanto anche un Alimentatore può essere di tipo elettrico, meccanico o misto.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    In realtà io tengo in considerazione anche i carburatori, ma cmq il mio dubbio riguardava il fatto che se io devo costruire un iniettore un parametro dovrà essere di tipo tipo_alimentatore (fatto con l'enum), ma se metto l'enum su alimentatore non avrei questo tipo a disposizione nel Main.cpp (stessa cosa ovviamente se lo metto in iniettore). Non so se mi sono spiegato.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Sorry avevo letto male la gerarchia, ma non cambia il senso. Invece di avere l'enum in alimentatore la metti in componente.
    Nel momento in cui hai Iniettore<Alimentatore<Componente, ogni sotto tipo eredita l'enum, per cui in ogni punto dove userai Iniettore puoi accedere all'enum come:
    Iniettore::elettrico
    Alimentatore::elettrico
    Componente::elettrico
    indifferentemente.
    Quanto al main. Ovunque userai un tipo iniettore/alimentatore/componente, avrai accesso all'enum, in quanto parte del tipo stesso.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Grazie mille. Sempre nella stessa gerarchia, o cmq nel cpp in generale, ha senso mettere un costruttore di copia virtuale.
    
    virtual Componente (const Componente* ogg): nome(ogg.come), etc... {}
    
    Per poi usarlo per in una classe automobile che usa puntatori per fare il metodo di clonazione, del genere:
    
    class Automobile {
    private:
    	Alimentatore* al;
    	Motore* mot;
    	Scarico* scar;     //alimentatore, motore e scarico sono sottotipi di componente
    	static componente* clone(componente* pOgg) {
    		return new componente(*pOgg);
    	}
    public:
    	.......
    }
    
    che poi il metodo di clonazione lo userei per il costruttore di copia di Automobile
    
    Automobile (const Automobile& o): al(clone(o.al)), mot (clone(o.mot)), scar(clone(o.scar)) {}
    
    Secondo voi ha senso o devo fare 3 metodi di clone() per ognuno dei tipi che uso???
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Si, è il pattern prototype.
    Nella gerarchia clone() va messa al livello più alto e ridefinita nelle sottoclassi in modo da rispecchiare la clonazione del tipo concreto.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Ho definito una classe veicolo in questo modo
    
    class Veicolo
    {
    private:
        std::string proprietario;
        std::string targa;
        Data data_immatricolazione;
        Data data_ultima_revisione;
        //componenti
        Motore* engine;
        Alimentatore* ali;
        Scarico* scar;
    public:
        Veicolo(std::string ,std::string ,const Data&, const Data&, Motore*, Alimentatore*,Scarico* );
        ~Veicolo();
        Veicolo (const Veicolo&);
        virtual void getInfo() const;
    
    };
    
    Veicolo::Veicolo(std::string prop, std::string tg, const Data& imm, const Data& rev, Motore *pM, Alimentatore *pA, Scarico *pS)
        :proprietario(prop), targa(tg), data_immatricolazione(imm), data_ultima_revisione(rev), engine(pM->clona()), ali(pA->clona()), scar(pS->clona())
        {}
    
    Veicolo::~Veicolo(){
        if (ali) delete ali;
        if (engine) delete engine;
        if (scar) delete scar;
    }
    
    adesso quando provo a fare una delete su un oggetto di tipo veicolo, il programma mi va in palla a causa di un segmentation fault. Se tolgo quei tre if e delete nel corpo del distruttore nessuna segmentation fault.
    Io quei if ce li ho messi per non creare garbage nello heap, ma non so per quale motivo causino segmentation fault.

    Io mi aspetterei questo: alla chiamata di un delete su un puntatore ad veicolo,
    -1 viene chiamato ~Veicolo(),
    -2 quindi eseguito il suo corpo cioè vengono chiamati ~Alimentatore(), ~Motore() e ~scarico().
    ~Motore() e ~scarico() sono oggetti con nessun puntatore nei campi dati e il costruttore è quello standard, inoltre sono due classi concrete => dovrebbe essere tutto ok.
    Alimentatore invece è una classe astratta, infatti ha distruttore virtuale, le sue derivate sono tutte concrete e non hanno puntatori come campi dati => anche qua ok.]
    -3 distruzione dei puntatori, che ormai non dovrebbero puntare più a niente, e degli altri campi dati.

    Non capisco proprio quel segmentation fault.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Il codice mi sembra corretto. Sicuro che i tre puntatori sia effettivamente clonati?
    Posta il codice delle classi.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Componente.h
    
    #ifndef COMPONENTE_H
    #define COMPONENTE_H
    #include "data.h"
    #include <string>
    
    
    class Componente //classe astratta (virtuale pura)
    {
    private:
        std::string produttore;
        Data data_produzione;
    public:
        Componente(std::string ="sconosciuto", const Data& =Data(1,12,2000));
        virtual ~Componente();
        virtual void getInfo() const =0;
        virtual Componente* clona() const =0;
    };
    
    #endif // COMPONENTE_H
    
    componente.cpp
    
    #include "componente.h"
    #include <iostream>
    
    Componente::Componente(std::string pr, const Data& dt): produttore(pr) , data_produzione(dt){}
    Componente::~Componente(){}
    void Componente::getInfo() const {
        std::cout<<"produttore = "<<produttore<<std::endl<<"data di produzione = "<<data_produzione<<std::endl;
        std::cout<<" il mio indirizzo e': "<<this;
            std::cout<<std::endl;
    }
    
    alimentatore.h
    
    #ifndef ALIMENTATORE_H
    #define ALIMENTATORE_H
    #include "componente.h"
    #include <string>
    #include <iostream>
    
    
    class Alimentatore: public Componente
    {
    public:
        Alimentatore(std::string , const Data&);
        virtual Alimentatore* clona() const=0;
        virtual ~Alimentatore();
    };
    #endif // ALIMENTATORE_H
    
    alimentatore.cpp
    #include "alimentatore.h"
    
    
    Alimentatore::Alimentatore(std::string prod, const Data& dt): Componente(prod, dt) {}
    Alimentatore::~Alimentatore() {}
    
    
    carburatore.h
    
    #ifndef CARBURATORE_H
    #define CARBURATORE_H
    #include "alimentatore.h"
    
    class Carburatore: public Alimentatore
    {
    
    public:
        Carburatore(std::string, const Data&);
        void getInfo() const;
        Carburatore* clona() const;
    };
    
    #endif // CARBURATORE_H
    
    carburatore.cpp
    
    #include "carburatore.h"
    
    Carburatore::Carburatore(std::string prod, const Data & dt):Alimentatore(prod, dt){}
    
    Carburatore* Carburatore::clona() const{
        return new Carburatore(*this);
    }
    
    void Carburatore::getInfo() const{
        Componente::getInfo();
        std::cout<<"CARBURATORE";
    
    }
    
    iniettore.h
    #ifndef INIETTORE_H
    #define INIETTORE_H
    #include "alimentatore.h"
    
    
    class Iniettore: public Alimentatore
    {
    public:
        enum modalita_iniezione {elettronica, meccanica, mista};
        Iniettore(modalita_iniezione , std::string, const Data&);
        void getInfo() const;
        Iniettore* clona() const;
    private:
        modalita_iniezione tipo_iniettore; //1 elettr, 2 meccanico, 3 misto
    };
    
    #endif // INIETTORE_H
    
    iniettore.cpp
    #include "iniettore.h"
    
    Iniettore::Iniettore(modalita_iniezione tp, std::string prod, const Data& dt):
        Alimentatore(prod, dt), tipo_iniettore(tp){}
    
    void Iniettore::getInfo() const {
        Componente::getInfo();
        std::cout<<"INIETTORE"<<std::endl;
        if (tipo_iniettore==elettronica) std::cout<<"elettronico"<<std::endl;
        if (tipo_iniettore==meccanica) std::cout<<"meccanico"<<std::endl;
        if (tipo_iniettore==mista) std::cout<<"misto"<<std::endl;
    }
    
    Iniettore* Iniettore::clona() const{
        return new Iniettore(*this);
    }
    
    motore.h
    #ifndef MOTORE_H
    #define MOTORE_H
    #include <iostream>
    #include "componente.h"
    
    class Motore: public Componente  //deve essere una classe astratta (deve avere dei metodi puri)
    {
    friend std::ostream& operator<< (std::ostream&, const Motore&);
    private:
        int n_cilindri;
        int cilindrata;                     //espresso in cc
        double rapporto_di_compressione;    // espressa in kW
        double coppia_massima;              // espressa in Nm
        bool sovralimentato;                // true indica se il motore lo è, se false è ASPIRATO
        //requisiti legali di conversione a GPL
        static int min_cilindrataGPL_aspirato;
        static int max_cilindrataGPL_aspirato;
        static int min_cilindrataGPL_sovralimentato;
        static int max_cilindrataGPL_sovralimentato;
    public:
        //non voglio costruttore a 0 parametri in quanto non posso definire un motore standard
        Motore(int , int, double, double, bool, std::string, const Data&);
    
        int getN_cilindri() const;
        int getCilindrata() const;
        double getRapporto_compressione() const;
        double getCoppia_max() const;
        bool isSovralimentato() const;
    
        void setN_cilindri(int);
        void setCilindrata(int);
        void setRapporto_compressione(double);
        void setCoppia_max(double);
        void setSovralimentato(bool);
    
        bool idoneitaGPL() const;  //se ci sono diversi requisiti di idoneità magari si fa polimorfa pura
        void getInfo() const;
        Motore* clona() const;
    };
    
    std::ostream& operator<< (std::ostream&, const Motore&);
    #endif // MOTORE_H
    motore.cpp
    #include "motore.h"
    #include "componente.h"
    
    Motore::Motore(int n_c, int cil, double r_d_c, double cop_max, bool turbo, std::string prod, const Data & dt_prod):
        n_cilindri(n_c), cilindrata(cil), rapporto_di_compressione(r_d_c),
        coppia_massima(cop_max), sovralimentato(turbo), Componente(prod, dt_prod) {}
    
    int Motore::min_cilindrataGPL_aspirato=890;
    int Motore::max_cilindrataGPL_aspirato=5500;
    int Motore::min_cilindrataGPL_sovralimentato=1335;
    int Motore::max_cilindrataGPL_sovralimentato=2250;
    
    Motore* Motore::clona() const{
        return new Motore(*this);
    }
    
    int Motore::getN_cilindri() const {return n_cilindri;}
    int Motore::getCilindrata() const {return cilindrata;}
    double Motore::getRapporto_compressione() const {return rapporto_di_compressione;}
    double Motore::getCoppia_max() const {return coppia_massima;}
    bool Motore::isSovralimentato() const {return sovralimentato;}
    
    void Motore::setN_cilindri(int n_c) {n_cilindri=n_c;}
    void Motore::setCilindrata(int cc){cilindrata=cc;}
    void Motore::setRapporto_compressione(double kW){rapporto_di_compressione=kW;}
    void Motore::setCoppia_max(double Nm){coppia_massima=Nm;}
    void Motore::setSovralimentato(bool turbo){sovralimentato=turbo;}
    
    bool Motore::idoneitaGPL() const{
        if (isSovralimentato())
            return (cilindrata>=min_cilindrataGPL_sovralimentato &&
                    cilindrata<=max_cilindrataGPL_sovralimentato ? true : false);
        else
            return (cilindrata>=min_cilindrataGPL_aspirato &&
                    cilindrata<=max_cilindrataGPL_aspirato ? true : false);
    }
    
    void Motore::getInfo() const{
        Componente::getInfo();
        std::cout<<"MOTORE:"<<std::endl;
        std::cout<<"cilindrata = "<<cilindrata<<" cc, n cilindri = "<<n_cilindri<<std::endl;
        std::cout<<"rapporto di compressione = "<<rapporto_di_compressione<<" kW, coppia max = "<<coppia_massima<<" Nm"<<std::endl;
        std::cout<<(sovralimentato ? "sovralimentato (turbo)" : "aspirato");
        std::cout<<std::endl;
    
    
    }
    
    //funzioni esterne
    std::ostream& operator << (std::ostream& canale, const Motore& o){
        canale<<"MOTORE:"<<std::endl;
        canale<<"cilindrata = "<<o.cilindrata<<" cc, n cilindri = "<<o.n_cilindri<<std::endl;
        canale<<"rapporto di compressione = "<<o.rapporto_di_compressione<<" kW, coppia max = "<<o.coppia_massima<<" Nm"<<std::endl;
        canale<<(o.sovralimentato ? "sovralimentato (turbo)" : "aspirato");
        return canale;
    }
    
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Non riscontro problemi col codice che hai postato. Prava a commentare una a una le delete nel distruttore di veicolo e vedi qual'è quella che da problemi.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Ho provato a metterli uno per uno e comunque va in segmentation fault. Funziona solo se li tolgo tutte e tre. Il debugger di Qt da sempre che il problema è causato dalla prima delle delete che viene chiamata a prescindere dall'ordine in cui le metto.
    Qualche consiglio, magari lato debugger (che io in realtà non so proprio usare), su come capire qual è il problema.
    Grazie comunque per l'attenzione. Buon Natale
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Sto provando a fare debugging con dei watchpoint messi sui distruttori, praticamente su ogni distruttore ho messo su corpo un
    cout<<"~classe()"<<endl e sembra che chiami tutti i distruttori che dovrebbe chiamare senza troppi problemi.

    il main è
    
    
        Scarico fid (1,1, "checcoscarichi", Data (12,12,12));
        Motore MultiJet (1200, 4, 120, 54.2, "fiatENGINE", Data(), false);
        Iniettore IN_IT (Iniettore::modalita_iniezione::meccanica,"luca", Data (12,12,12));   
        Veicolo LanciaY ("Luca Nobile", "AA123ZZ",Data(12,12,2012), Data(12,2,2016), &MultiJet,&IN_IT, &fid );
        cout<<"________________________________________"<<endl;
        delete &LanciaY;
        cout<<"____________________________________________"<<endl;
    
    l'output invece :
    
    ~data()
    ~data()
    ~data()
    ~data()
    ~data()
    ~data()
    ________________________________________
    ~Iniettore
    ~Alimentatore()
    ~componente()
    ~data()
    ~Motore
    ~componente()
    ~data()
    ~scarico
    ~componente()
    ~data()
    fine corpo distruttore
    ~data()
    ~data()
    
    i distruttori di data prima della linea sono le distruzioni dei parametri passati per valore assuluto ai vari costruttori, poi abbiamo i distruttori chiamati dal corpo di ~veicolo() e poi quelli chiamati in maniera implicita. ovviamente le due std::string non danno output perché sono da libreria ma cmq credo al 99% che non diano problemi. E poi il programma smette di funzionare!

    che vuol dire????
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    È possibile che non sia un problema del codice, ma di qt?
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Se il codice che hai riportato è corretto, il problema è solo tuo!
    
        Veicolo LanciaY ("Luca Nobile", "AA123ZZ",Data(12,12,2012), Data(12,2,2016), &MultiJet,&IN_IT, &fid );
        cout<<"________________________________________"<<endl;
        delete &LanciaY;
    
    Si può sapere perché fai la delete su un oggetto piazzato sullo stack? E' normale che si sfasci tutto! La delete va invocata solo ed esclusivamente su puntatori allocati con new
    Togli quella delete e il tutto funziona.
  • Re: [RISOLTO]Dubbio su utilizzo tipo enum in una gerarchia di classi

    Grazie mille! Non pensavo che chiamare la delete su un puntatore verso lo stack sfasciasse tutto.
Devi accedere o registrarti per scrivere nel forum
14 risposte