Write on a File with polymorphism

Hi! I got some problems with the passing of a variable ostream to a function.
I got three classes, Letters (Lettere) that is derived from Manuscripts (Manoscritti) and Manuscripts List (ElencoManoscritti) that is formed by a static array of pointers to Manoscritti. ElencoManoscritti has a function that should write on a file void memorizza(); by calling
the function virtual void memorizza_dati(ostream&); of Manuscripts and Letters (I want a polymorph behavior).
The problem is that memorizza() doesnt write ont he file (so doesnt call properly memorizza_dati()) and i dont know why

Sorry if the text is in italian!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  class Lettera : public Manoscritto{
public:
	Lettera(int c=0, string a="unknown", int n=0, string f=" ", string m="uknown", string d="uknown") : Manoscritto(c, a, n, f), Mittente(m), Destinatario(d) {}
	virtual void visualizza_dati();
    Lettera operator=(Lettera&);
private:
	string Mittente;
	string Destinatario;
};

Lettera Lettera::operator=(Lettera& m){
	Codice=m.Codice;
	Autore=m.Autore;
	nPag=m.nPag;
	Formato=m.Formato;
	Mittente=m.Mittente;
	Destinatario=m.Destinatario;
	return *this;
}

void Lettera::visualizza_dati(){
	cout<<"La lettera "<<Codice<<", scritta da "<<Autore<<" ha "<<nPag<< "ed e' in formato "<<Formato<<"."<<endl;
	cout<<"Il mittente e' "<<Mittente<<", il destinatario e' "<<Destinatario<<"."<<endl;
}

void Lettera::memorizza_dati(ostream& l){
    Manoscritto::memorizza_dati(l);
    l<<cout<<"Il mittente e' "<<Mittente<<", il destinatario e' "<<Destinatario<<"."<<endl;
}

class Manoscritto{
friend bool operator<(Manoscritto& m, Manoscritto& l);
friend ostream& operator<<(ostream&, Manoscritto&);
public:
	Manoscritto(int c=0, string a="unknown", int n=0, string f=" ") : Codice(c), Autore(a), nPag(n), Formato(f) {}
	virtual void visualizza_dati();
    virtual void memorizza_dati(ostream&);
    Manoscritto operator=(Manoscritto& m);
protected:
	int Codice;
	string Autore;
	int nPag;
	string Formato;
};

Manoscritto Manoscritto::operator=(Manoscritto& m){
	Codice=m.Codice;
	Autore=m.Autore;
	nPag=m.nPag;
	Formato=m.Formato;
	return *this;
}

ostream& operator<<(ostream& out, Manoscritto& m){
	cout<<"Il manoscritto "<<m.Codice<<", scritto da "<<m.Autore<<" ha "<<m.nPag<< "ed e' in formato "<<m.Formato<<"."<<endl;

	return out;
}

bool operator <(Manoscritto &m, Manoscritto &l){
	if(m.Codice<l.Codice) return true;
	else return false;
}

void Manoscritto::visualizza_dati(){
	cout<<"Il manoscritto "<<Codice<<", scritto da "<<Autore<<" ha "<<nPag<< "ed e' in formato "<<Formato<<"."<<endl;
}

void Manoscritto::memorizza_dati(ostream& l){
    l<<"Il manoscritto "<<Codice<<", scritto da "<<Autore<<" ha "<<nPag<< "ed e' in formato "<<Formato<<"."<<endl;
}

const int MaxNum=10;

class ElencoManoscritti{
public:
	ElencoManoscritti() : nManoscritti(0) {}
	void insert(Manoscritto& m);
	void memorizza();
private:
	int nManoscritti;
	Manoscritto* Elenco[MaxNum];
};

void ElencoManoscritti::insert(Manoscritto& m){
	Manoscritto* temp=&m;
	if(nManoscritti+1<MaxNum){
	Elenco[nManoscritti+1]=temp; nManoscritti++;}
	else cout<<"Elenco Pieno!"<<endl;

}

void ElencoManoscritti::memorizza(){
	    ofstream libro("Manoscritti.txt",ios::out | ios::app);

		if(!libro){
			cerr<<"Impossibile aprire il file."<<endl;
			exit(1);
		}


		libro<<"Codice    Autore      nPag    Formato"<<endl;
        libro<<"_____________________________________"<<endl;

        for(int i=0;i<nManoscritti;i++)
        Elenco[i]->memorizza_dati(libro);

        libro.close();
}

int main(){

     Manoscritto m1(1,"jack",10,"txt"), m2(2,"rob",20,"pdf");
     ElencoManoscritti E;
     E.insert(m1);
     E.insert(m2);

     E.memorizza();

	 return 0;
}
1. Declare and implement virtual functions memorizza_dati() and visualizza_dati() in the base class.

2. In std::ostream& operator << ( std::ostream& stm, const Manoscritto& m ) and
ElencoManoscritti::memorizza() call the virtual function.

3. Override the virtual functions memorizza_dati() and visualizza_dati() in each derived class

And make these const-correct. http://www.parashift.com/c++-faq-lite/const-correctness.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>

struct Manoscritto
{
    virtual ~Manoscritto() {}

    // ...

    virtual std::ostream& memorizza_dati( std::ostream& stm ) const // 1
    {
        std::cout << "memorizza_dati for Manoscritto" ;
        // TODO: replace the above with writing out the actual stuff

        return stm ;
    }

    // ...
};

std::ostream& operator << ( std::ostream& stm, const Manoscritto& m ) // 2
{ return m.memorizza_dati(stm) ; }

struct Lettera : public Manoscritto
{
    // ...

    virtual std::ostream& memorizza_dati( std::ostream& stm ) const override // 3
    {
        // call base class function if required
        // Manoscritto::print(stm) ;

        std::cout << "memorizza_dati for Lettera" ;
        // TODO: replace the above with writing out added stuff

        return stm ;
    }

    // ...
};

int main()
{
    Manoscritto m1, m2 ;
    Lettera l1, l2, l3 ;

    Manoscritto* Elenco[] = { &m1, &l1, &l2, &m2, &l3 } ;

    for( Manoscritto* p : Elenco ) std::cout << *p << '\n' ;

    std::cout << '\n' ;

    // or:
    for( Manoscritto* p : Elenco ) p->memorizza_dati(std::cout) << '\n' ;
}

http://ideone.com/NttV6a
Topic archived. No new replies allowed.