Problema gestione di pile con classi

di il
10 risposte

Problema gestione di pile con classi

Salve ragazzi è la prima volta che scrivo qui , sono nuovo ed inesperto nella materia e non trovando risposte altrove ho deciso di chiedere aiuto qui. Ho una classe template di pile , ma non riesco a generare una classe che possa gestire un array ( con puntatori) di pile , copio quanto basta del codice per semplicità : 

template <typename T>
class pila
{
   public : 
       typedef T tipoelem;
    pila(int dim);
    private :
       unsigned int testa ;
       tipoelem* elem ; 
};    
template <typename T>
pila<T>:: pila(int dim)
{
   testa = 0;
   elem = new tipoelem[dim]; 
}
 
template <typename T>
class MultipleStack 
{
   public :    
       MultipleStack(int dimStack ,int dimPila); 
   private :
       pila<T>* stack;  
};
  
template <typename T>
MultipleStack<T>::MultipleStack( int dimStack ,int dimPila)     
{
   stack = new pila<T>[dimStack];              // il problema è qui , speravo si potesse fare  un' allocazione di questo tipo
   for(int pos = 0; pos < dimStack ; pos++)
    { 
        stack[pos](dimPila);     
    }
}

// aggiungo che il secondo dato in ingresso nel costruttore di multipleStack l'ho aggiunto solo per fare dei test ,
// in realtà le pile possono variare di dimensione , poiché scritto così sembra che debbano avere la stessa dimensione

10 Risposte

  • Re: Problema gestione di pile con classi

    Puoi spiegare meglio qual è il problema? 

  • Re: Problema gestione di pile con classi

    09/12/2022 - Alexv ha scritto:


    Puoi spiegare meglio qual è il problema? 

    Non ho idea di come impostare il costruttore di MultipleStack , così da creare un'array di pile.  

    In pratica se utilizzo il  costruttore  pila<T>::pila(int) nel main (e faccio vari test sulle pile con alcune funzioni della classe pila ) non ho alcun problema.
    Ma nel momento in cui creo la classe MultipleStack , ed il suo costruttore   MultipleStack<T>::MultipleStack() , per gestire un'array di pile , quando avvio il compilatore  mi dice che :

    1)  Errore C2512 'pila<T>': non è disponibile alcun costruttore predefinito appropriato 

    2) Errore  C2064 Il termine non restituisce una funzione che accetta 1 argomenti

    poiché l'avevo pensato così : 

    template <typename T>
    MultipleStack<T>::MultipleStack( int dimStack ,int dimPila)     
    {
       stack = new pila<T>[dimStack];                    // l'array stack ha dimensione dimStack , e contiene delle pile , tutte dello stesso tipo
       for(int pos = 0; pos < dimStack ; pos++)    //  qui decido che ogni pila di questo array ha le stesse dimensioni 
        { 
            stack[pos](dimPila);     
        }
    }

  • Re: Problema gestione di pile con classi

    Allora, la new costruisce n oggetti chiamando il loro costruttore senza parametri, ma tu non ne hai previsto uno per pila<T>, quindi non è fattibile. 

    Ci sono vari modi con cui puoi aggirare il problema.

    1. Invece di fare un array di pila<T>, fai un array di puntatori a pila, dopodiché chiami la new pila<T>(dim) su ognuno di essi.
    2. Usare la malloc del C anziché la new. Questa si limita ad allocare lo spazio, dopodiché in ogni posizione del vettore costruisci una pila<T>. 
    3. Usare la classe std::vector<pila<T>> . Prima crei un vettore vuoto nel multiStack, poi usi i metodi “emplace" per aggiungere le pile. I metodi emplace accettano gli argomenti di qualunque costruttore di pila<T> per costruire direttamente gli oggetti nel vettore man mano che li aggiungi. Io userei questa soluzione. 
    4. Fare overloading dell'operatore new, ma richiede un po' di artifizi (se trovo il tempo posso provare).
    5. Usare la classe allocator per allocare prima la memoria del vettore di multiStack e poi costruirci dentro le pila<T>, ma è solo un modo più complicato del punto 3. 
  • Re: Problema gestione di pile con classi

    Grazie mille per la risposta Alexv , ho provato i punti 1 e 2 e praticamente se non ho il costruttore senza parametri in ingresso non funziona nulla , quindi è necessario dare una dimensione fissa al dato tipoelem ( nel costruttore della pila , oppure nella dichiarazione del membro private : tipoelem* elem; ) perché il tutto funzioni , eppure pensavo si potesse decidere sia la dimensione di ogni pila che la dimensione dello stack di pile...
    Comunque il problema ora è che non riesco a lavorare sulle singole pile dell'array stack , cioè l'allocazione sembra funzionare , ma nel main non riesco a fare cose del tipo : 

    stack[0].pushIn( 3 ); stack[0].pushIn( 4 ); stack[0].pushIn( 5 );….
    stack[1].pushIn( 45 ); stack[1].pushIn( 55 ); stack[1].pushIn( 65 );….
    ….
    stack[5].pushIn(105); stack[5].pushIn(115); stack[5].pushIn(125);….

    Se non sbaglio dovrei poterlo gestire anche cosi (?). Nel caso pensavo di utilizzare delle funzioni della classe per accedere direttamente alle pile dello stack.
    Spero riuscirai a schiarirmi le idee :D 

  • Re: Problema gestione di pile con classi

    Puoi spiegarti meglio? Fai vedere anche come hai implementato. Che tipo è “stack” ? 

  • Re: Problema gestione di pile con classi

    Stack l'ho lasciato come era in principio , ho solo modificato il costruttore di pila , così non ha parametri in input , con la  limitazione di non poter decidere la dimensione di ogni singola pila dello stack , che ho fissato a 10.
    Comunque mi sbaglio , ho provato con New e malloc , sembra che non costruisce niente , mando il codice se riesci a darmi una mano..
    Magari mi fai un esempio per costruire lo stack..  grazie per la pazienza xD

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    template <typename T>
    class pila
    {
    public:
       typedef T tipoelem;
       pila();
       ~pila();
       void pushIn(T elemento);
       tipoelem leggiTesta();
       void remove();
       bool pilavuota();
    private:
       int testa;
       tipoelem* elem;
    };
    template <typename T>
    pila<T>::pila(){testa = 0; elem = new tipoelem[10];}
    template <typename T>
    pila<T>::~pila() { delete[] elem; }
    template <typename T>
    void pila<T>::pushIn(T elemento) { elem[testa] = elemento;   testa++; }
    template<typename T>
    T pila<T>::leggiTesta() { return elem[testa - 1]; }
    template<typename T>
    void pila<T>::remove()
    {
       if (!pilavuota()) { testa -= 1; }
       else { cout << "la pila e' vuota"; }
    }
    template<typename T>
    bool pila<T>::pilavuota()
    {
       return (testa == 0);
    }
    template <typename T>
    class MultipleStack : public pila<T>
    {
       public:
           MultipleStack(int dimStack);
           void MultiIn(int posizione, T elem);
       private:
           pila<T> *stack;
           int dim;
    };
    template <typename T>
    MultipleStack<T>::MultipleStack(int dimStack)
    {
       dim = dimStack;  
       stack = (pila<T>*)malloc(sizeof(pila<T>) * dimStack);
       cout << "dimensione dello stack :" << dim ;
       /*
           for(int i = 0; i<dimStack; i++)       
           {
               stack[i]();    
           }
       */
    }
    template <typename T>
    void MultipleStack<T>::MultiIn(int posizione, T elem)
    {
       // stack[posizione].pushIn(elem);
    }
    
    int main()
    {
       MultipleStack <int> gino(5);
       return 0;
    }
    
  • Re: Problema gestione di pile con classi

    Infatti malloc non costruisce niente, per questo non ha problemi con i costruttori. Per popolare il multistack con costruttore di pila parametrizzato prova così:

    for(int i = 0; i<dimStack; i++)       
          {
              stack[i] = pila<T>(14);   
          }
  • Re: Problema gestione di pile con classi

    Ho fatto delle prove e funziona come scritto sopra, però c'e un problema: per deallocare serve la free, che non chiama i distruttori delle pile. Quindi nel distruttore del multistack devi chiamare manualmente i distruttori di tutte le pile e infine deallocare stack.

    Penso che il modo più semplice (se non vuoi usare il vector) sia prevedere un costruttore senza parametri per la pila e prevedere funzioni per ridimensionare, e allocare tutto con la new. Non dovrebbe essere un problema se lasci anche l'altro costruttore. 

  • Re: Problema gestione di pile con classi

    Non capisco perché a me non funzionava il ciclo for che hai scritto sopra , ma hai cambiato qualcosa nel codice ?

    Perché se utilizzi la new in quel modo (con le tonde) ,  non mi è chiaro in che punto definisci la dimensione dello stack. Cioè come e dove gli dici che Stack ha dimensione dimStack  ?  

    Nel frattempo io per la disperazione ho risolto utilizzando un costruttore di pila senza parametri che chiede la dimensione da tastiera , e quindi quando richiamo : 

    template <typename T>
    MultipleStack<T>::MultipleStack(int dim)   // costruttore di array di pile con dimensione in input
    {
       stack = new pila<T>[dim];
    }  

    mi fa costruire una pila alla volta in base alla dimensione dello stack..

  • Re: Problema gestione di pile con classi

    Il ciclo di sopra era conseguente all'allocazione di stack con la malloc. Dopodiché ho chiamato il costruttore con un parametro (che va ridefinito). È comunque una soluzione grezza, meglio la tua a questo punto. 

Devi accedere o registrarti per scrivere nel forum
10 risposte