Chiarimenti su un comportamento polimorfo di una funzione di stampa

di il
2 risposte

Chiarimenti su un comportamento polimorfo di una funzione di stampa

Salve, volevo chiedere un chiarimento circa il comportamento polimorfo di una funzione di stampa. In particolare Ho una gerarchia di opere d arte: la classe base è scheda da cui derivano: opere scultoree (La chiamerò OperaS)ed opere Pittoriche (la chiamerò OperaP). Mi si chiedeva di implementare un Catalogo di schede avente un titolo con rappresentazione mediante un array allocato dinamicamente e di prevedere un' operatore che stampasse i dati relativi all' opera. Per far cio ho dapprima implementato nelle classi OperaS, OperaP e scheda una funzione Print in modo tale che essa sia virtual e poi nei rispettivi operatori di shift ho richiamato tale funzione Print.
Classe Scheda
	class Scheda{
		friend ostream & operator<<(ostream &,const Scheda &);
		friend istream & operator>>(istream &,Scheda &);
		private:
			char * Titolo;
			char * Descrizione;
			static const int N=10;
			char Codice [N];
			Autore Aut;
			
			virtual void Print (ostream &)const;
			
Implementazione Print e operatore di shift:
void Scheda::Print (ostream & out)const{
	out << Titolo << ' ' << Descrizione << ' ' << Codice << ' ' << Aut;
}
ostream & operator<<(ostream & out,const Scheda & S){
	S.Print(out);
	return out;
}		

Mentre per la classe OperaP(riporto solo l' implementazione della print e dell oepratore di shift di una sola derivata, in quanto dell' altra derivata OperaS il procedimento è analogo):

void OperaP::Print (ostream & out)const{
	out << (Scheda)*this << ' ' << Tecnica << Tipo;
}
ostream & operator<<(ostream & out,const OperaP & O){
	O.Print(out);
	return out;
}

Mentre per la classe Catalogo ho implementato semplicemente quest operatore di shift che riesce a stampare qualsiasi elemento della gerarchia.
	class Catalogo{
		
		friend ostream & operator << (ostream &,const Catalogo &);
		private:
			char * Titolo;
			T * V;
			int nelem;
			int riemp;
			
			
			
	ostream & operator << (ostream & out,const Catalogo & C){
	for(int i=0;i<C.riemp ; i++) out << *C.V[i] << std::endl;
	return out;
}
			
			


La mia domanda era la seguente: E' cosi che bisognava fornire un uso polimorfo dell' operatore di shift per quanto riguarda le classi Scheda-OperaP in modo che Catalogo stampi tutte le info necessarie?
Inoltre l' upcasting che io eseguo nella Print di OperaP è il seguente:
(Scheda)*this
Tuttavia negli operatori di shift o in altre circostanze la prof ci faceva fare l' upcasting di un oggetto in questo modo
(Base&)Oggetto
Nel caso di OperaP se seguissi l' upcasting fatto dalla prof ossia facessi
(Scheda&)*this
, il programma mi va in crash.
Non riesco a capire il perchè di questa differenza e non riesco a spiegarmi il perchè il mio upcasting non da alcuna sorta di errore.
Grazie in anticipo

2 Risposte

  • Re: Chiarimenti su un comportamento polimorfo di una funzione di stampa

    0.1) SEGUI PEDISSEQUAMENTE gli standard di scrittura del codice:

    https://isocpp.org/wiki/faq/coding-standard
    https://google.github.io/styleguide/cppguide.htm

    NON inventarti un TUO standard!
    Fara' anche ""figo"" ma il 99.999999999% di chi legge il TUO codice (che SEGUE gli standard) non ci capira' niente.

    0.2) NON RISPARMIARE caratteri solo per scrivere ""meno codice"". E' 1.000.000 di volte megli avere codice CHIARO che codice scritto in modo compatto. OGNI variabile, classe, metodo, ... DEVE AVERE un nome significativo e COMPRENSIBILE.

    Quindi:

    NON "OperaS" MA "OperaScultorica" oppure "Scultura" (o quello che ti sembra meglio)
    NON "OperaP" MA "OperaPittorica" o "Quadro" (come sopra)

    Visto che il codice e' C++, NON USARE "char*" MA "std::string"

    1) il codice non e' completo QUINDI il problema, nel 99% dei casi NON E' dove tu pensi che sia.

    2) l'upcasting, e' spesso automatico.
    
    #include <iostream>
    #include <vector>
    #include <string>
    
    struct Base {
        int fi;
    
        Base(int i):fi(i){ }
    };
    
    struct Derived : public Base {
        int fj;
    
        Derived(int i, int j):Base(i),fj(j){ }
    };
    
    void appmain(const std::vector<std::string>& apps){
        Base b{1};
        Derived d{2,3};
        Base c{44};
    
        c = d;
        c = Base(33);
        c = (Base&)d;
        c = Base(11);
        c = *(Base*)(&d);
        c = Base(22);
        c = (Base)d;
    
        std::cout << c.fi << std::endl;
    }
    

    Cosi' come l'hai scritto, non sembra esserci errori.
  • Re: Chiarimenti su un comportamento polimorfo di una funzione di stampa

    Se compila, posta almeno le implementazioni delle funzioni che hai usato, e anche i costruttori delle classi.
    Che cos'è il T* della classe Catalogo?
Devi accedere o registrarti per scrivere nel forum
2 risposte