[C++] Stampa Pila di oggetti

bblack25
Buonasera a tutti,
avrei bisogno di aiuto con la stampa di una pila dinamica.La traccia mi chiede di implementare una pila di Pratiche.Pratiche è una classe che eredita altre due classi(Carta e Patente) e ognuna contiene una funzione Stampa().La classe pila deve contenere una funzione Print() che consente di stampare tutte le pratiche presenti nella pila che possono essere sia Carte che Patenti.Il mio problema è che quando chiamo la Print() nel main(poichè gli oggetti sono Pratiche)non mi stampa le informazioni aggiuntive di Carta e Patenti pur adottandoo il polimorfismo nelle funzione Stampa() di ogni classe.Spero di essere stato chiaro...
#ifndef PILA_H
#define PILA_H

#include<iostream>
#include"Pratica.h"
#include"Patente.h"
#include"Carta.h"
using namespace std;

typedef Pratica E;
struct Record{
    E elem;
    Record* next;
};
typedef Record* Ptr;

class Pila{
private:
    Ptr l;
public:
    Pila(){l=0;}
    void Push(const E&);
    void Pop(E&);
    void Top(E&)const;
    bool Empty()const;
    bool Full()const;
    void Print()const;
    ~Pila();
};


void Pila::Push(const E&e){
    Ptr q=new Record;
    q->elem=e;
    q->next=l;
    l=q;
}

void Pila::Pop(E&e){
    Ptr temp=l;
    if(temp!=0){
        e=temp->elem;
        l=temp->next;
        delete temp;
    }
}

void Pila::Top(E&e)const{
    if(l!=0)
    e=l->elem; 
}

bool Pila::Empty()const{
    return l==0;
}

bool Pila::Full()const{
    return false;
}

void Pila::Print()const{
    Ptr temp=l;
    while(temp){
        temp->elem.Stampa();
        temp=temp->next;
    }
}
        
     
Pila::~Pila(){
    Ptr temp;
    while(l){
        temp=l;
        l=temp->next;
        delete temp;
    } 
}

Risposte
claudio862
In C++ il polimorfismo funziona solo con puntatori e riferimenti.

typedef Pratica E;
struct Record{
    E elem;
    Record* next;
};

Nella tua pila memorizzi oggetti di tipo Pratica, non puntatori o riferimenti ad essi. Quando inserisci una "Carta" nella pila, prima viene convertita in "Pratica" (fenomeno chiamato slicing). A quel punto l'oggetto è diventato una "Pratica", variabili e funzioni membro aggiuntive della classe "Carta" sono perse, non esistono più. Non puoi più riottenere l'originale "Carta" nemmeno con un cast.

Una soluzione può essere memorizzare nella pila puntatori a Pratica (o riferimenti, ma qui ci sarebbero molte più complicazioni).

bblack25
Ah avevo pensato che poichè nella Print() avevo usato la funzione Stampa() virtuale ridefinita in Carta e Patente, se nel main facevo una cosa del genere P.Print() stampasse correttamente.Quale pensi che sia la soluzione meno "dispendiosa"?

claudio862
"bblack25":
Ah avevo pensato che poichè nella Print() avevo usato la funzione Stampa() virtuale ridefinita in Carta e Patente, se nel main facevo una cosa del genere P.Print() stampasse correttamente.

Il fatto è che una volta inserito un oggetto nella pila non è più un oggetto di tipo Carta o Patente. È un oggetto di tipo Pratica. Prova così:

int main()
{
    Carta a = Carta(...);
    Pratica b = a;
    b.Stampa();
}

vedrai che usa la funzione della classe base Pratica.

"bblack25":
Quale pensi che sia la soluzione meno "dispendiosa"?

Cosa intendi con "meno dispendiosa"?

Userei una pila di puntatori (o magari di smart pointer). Il problema è che la pila non può contenere oggetti, solo puntatori ad oggetti, e questo fatto non è trasparente ai client della pila. Cioè quando usi una pila, devi preoccuparti tu di allocare la memoria per ogni oggetti, inserirlo nella pila, e quando lo rimuovi deallocare la memoria. Non è un'operazione che fa la pila. Però del resto se il client usa oggetti polimorfici deve per forza usare dei puntatori, quindi non dovrebbe essere un grosso problema.

bblack25
Si ho capito, il problema sta proprio nell'inserimento visto che gli oggetti della Pila che ho dichiarato sono delle Pratiche.
Con i puntatori il problema si può risolvere nel caso di oggetti:
Patente F=Patente(...);
Pratica* L=&F;
L->Stampa();

Però il mio problema sta proprio nella stampa della Pila con la Print().Ho capito quello che proponi di fare ma non saprei da dove partire perciò mi chiedevo se si poteva stampare la Pila di oggetti(Patenti o Carte) senza cambiare l'implementazione della Pila ma solo il main... :?

apatriarca
All'interno di ogni nodo devi inserire un puntatore alle pratiche. Non c'è alcun modo di aggirare questo problema.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.