Pages: [1]   Go Down
Print
Author Topic: dubbio sul codice  (Read 1099 times)
0 Members e 1 Utente non registrato stanno visualizzando questa discussione.
Gerasia
Matricola
*
Offline Offline

Posts: 31


« on: 09-03-2018, 16:31:05 »

salve a tutti di seguito posterò un codice e mi chiedevo se l'overload dell'operatore << fatto in questo modo sia corretto o meno:
Code:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <typeinfo>
using namespace std;
class A{
    private:
        string x;
    public:
        A(string _x):x(_x){}
        string getX(){
            return x;
        }
        virtual string guess()=0;
        bool doppia(){
            for(int i=0; i<x.length(); i++){
                for(int j=i+1; j<x.length(); j++){
                    if(x[i]==x[j])
                        return 1;
                }
            }
            return 0;
        }
        friend ostream &operator <<(ostream &sx, A &dx);
};
class B:public A{
    private:
        string y;
        float pos;
    public:
        B(string s, float p):A(s.substr(0,10)),pos(p),y(s.substr(10,10)){}
        char estrai(){
            return y[pos];
        }
        string guess(){
            string ciaone="";
            for(int i=0; i<10; i++)
                ciaone=ciaone+getX()[i]+y[i];
            return ciaone;
        }
        friend ostream &operator<<(ostream &sx, B &dx);
};
class C:public A{
    private:
        string z;
    public:
        C(string s):A(s.substr(0,10)),z(s.substr(11,10)){}
        string guess(){
            return z+getX();
        }
        friend ostream &operator<<(ostream &sx, C &dx);
};
//OVERLOAD
ostream &operator<<(ostream &sx, A &dx){
    if(typeid(dx)==typeid(B))
        return sx<<"Class B: x="<<dx.x<<((B&)dx);
    else
        return sx<<"Class C: x="<<dx.x<<((C&)dx);
}
ostream &operator<<(ostream &sx, B &dx){
    return sx<<" guess()="<<dx.guess()<<" estrai()="<<dx.estrai()<<endl;
}
ostream &operator<<(ostream &sx, C &dx){
    return sx<<" guess()="<<dx.guess()<<" z="<<dx.z<<endl;
}
int main(){
    const int DIM=20;
    A* vett[DIM];
    srand(333675333);
    for(int i=0; i<DIM; i++){
        string str="";
        for(int j=0; j<20; j++)
            str+=(char)('a'+rand()%26);
        if(rand()%2==1)
            vett[i]=new B(str,(float)(rand()%10));
        else
            vett[i]=new C(str);
    }
    cout<<"doppi:"<<endl;
    for(int i=0; i<DIM; i++){
        if(!vett[i]->doppia())
            cout<<i<<" ";
    }
    cout<<endl;
    string est="";
    for(int i=0; i<DIM; i++){
        if(typeid(*vett[i])==typeid(B))
            est+=((B*)vett[i])->estrai();
    }
    cout<<"estratto:"<<endl<<est<<endl;
    char P[20][20];
    for(int i=0; i<20; i++){
        for(int j=0; j<20; j++){
            if(typeid(*vett[i])==typeid(B))
                P[i][j]=((B*)vett[i])->guess()[j];
            else
                P[i][j]=((C*)vett[i])->guess()[j];
        }
    }
    cout<<"diagnale:"<<endl;
    for(int i=0; i<20; i++){
        cout<<P[i][i];
    }
    //COUT DI TUTTI GLI OGGETTI
    cout<<endl<<"overload:"<<endl;
    for(int i=0; i<20; i++){
        cout<<i<<") "<<*vett[i];
    }
}
Logged
fmessina
Moderator
Apprendista Forumista
*****
Offline Offline

Posts: 125


« Reply #1 on: 18-03-2018, 08:56:35 »

Ciao Gerasia,

il meccanismo che hai implementato funziona correttamente, tuttavia ti consiglio di far uso del polimorfismo, che permette di delegare il riconoscimento del tipo (classe B o C) alla coppia compilatore-linker.

//OVERLOAD
 55 ostream &operator<<(ostream &sx, A &dx){
 56     if(typeid(dx)==typeid(B))
 57         return sx<<"Class B: x="<<dx.x<<((B&)dx);
 58     else
 59         return sx<<"Class C: x="<<dx.x<<((C&)dx);
 60 }

Facendo riferimento al frame di codice riportato sopra, nel caso in cui si definiscano altre classi derivate, ad esempio dalla classe A (magari un centinaio), saresti costretto a modificare il corpo della funzione di overloading dello operatore << per gestire tutti questi altri casi!

Se invece fai uso di una funzione virtual (nei nostri esercizi la chiamiamo put() ) dichiarata nella classe base e opportunamente invocata nel corpo del metodo di overloading dello operatore <<, dovrai occuparti di implementare tale funzione (la put())  nelle nuove classi derivate (overriding) , facendo attenzione -- se e' il caso (cioe' se serve) -- , di invocare anche l'implementazione della classe base (A::put(...)).

Inoltre non avrai bisogno di ridefinire l'overloading dell'operatore << per ogni nuova classe derivata come hai fatto in quell'esempio.

Allora quando far uso degli strumenti di RTTI? Quando non se ne puo' fare a meno, cioe' quando compilatore e/o linker non possono aiutarci. Ad esempio hai un puntatore alla classe base e vorresti invocare un metodo f() definito in B ma non in A. Allora puoi far uso di dynamic_cast oppure di typeid().

Spero di esserti stato d'aiuto, se mi sfugge qualcosa fatemelo notare per favore.
« Last Edit: 18-03-2018, 14:32:09 by fmessina » Logged
Gerasia
Matricola
*
Offline Offline

Posts: 31


« Reply #2 on: 19-03-2018, 22:07:09 »

okok grazie mille prof!
Logged
Pages: [1]   Go Up
Print
Jump to: