Newsgroup: it.comp.lang.c++
Titolo: Ereditarietà Polimorfica

Salve a tutti.
Avrei una domanda da porre, alla quale ho già dato una mia risposta
preliminare (NO) sulla possibilità o meno di realizzare un'idea
"strana" che mi è balenata nella mente. Dato per assunto di non essere
onnisciente vorrei un parere.
Ecco quindi la domanda:
Date:
1) Una classe ABC detta Base_ABC che definisce solo funzioni virtuali
pure.
2) Una classe Derivata_1 che eredita pubblicamente Base_ABC ed
implementa almeno una funzione virtuale definita dalla base e che non
definisce nessun altra nuova funzione.
3) Una Classe Derivata_2 che eredita pubblicamente Base_ABC ed
implementa solo le stesse funzioni implementate da Derivata_1.
Grazie ad una semantica particolare o un typedef ad-oc o un "gioco" di
namespace ed using o un eredità pubblica virtuale o un qualsiasi altro
metodo o pattern, è possibile realizzare una classe Derivata_Ultima
che possa essere associata a run-time ad classe base a scelta tra
Derivata_1 o Derivata_2?
Se fosse possibile, in che modo si può realizzare una struttura del
genere?
Spero di essere stato chiaro.
Ringrazio chiunque mi possa dare una risposta.
Saluti
Giuseppe Ruggiero

 Derivata_1 o Derivata_2?
Non è quello che faresti usando un Base_ABC* ?
Ciao!


Usando una sola classe Derivata_Ultima no, ma, secondo me, è sbagliato 
il concetto riguardo a 'è' oppure 'ha'. Se deve usare o l'una o l'altra, 
non è una Base_ABC, ma ha una Base_ABC.
Quindi no ereditarietà, ma contenimento-delega.
Ciao


Quello che intendo è questo:
class Base_ABC {
public:
    Base_ABC(){};
    virtual void test() =0;
};
class Derivata_1 : public Base_ABC {
public:
    Derivata_1(){};
    virtual void test(){std::cout << "test da Derivata_1\n";};
};
class Derivata_2 : public Base_ABC {
public:
    Derivata_2(){};
    virtual void test(){std::cout << "test da Derivata_2\n";};
};
class Derivata_Ultima : public ??? {
public:
    Derivata_Ultima(){};
    void eseguiTest(){ this->test();};
};
int main(){
//Dichiarazione dell'oggetto "testami" scegliendo sia la classe
dell'oggetto che la classe da cui ereditare
??? Derivata_Ultima ??? Derivata_1 ??? testami;
testami.eseguiTest(); // Derivata_1::test
// Cambio di classe base da usare
??? testami ??? Derivata_2;
testami.eseguiTest(); // Derivata_2::test;
}
Output:
test da Derivata_1
test da Derivata_2
--------------------------------------------------------------------------------------------------------------------------------
Sostanzialmente quello che si potrebbe ottenere con un artificio del
tipo:
class Base_ABC {
public:
    Base_ABC(){};
    virtual void test() =0;
};
class Derivata_1 : public Base_ABC {
public:
    Derivata_1(){};
    virtual void test(){std::cout << "test da Derivata_1\n";};
};
class Derivata_2 : public Base_ABC {
public:
    Derivata_2(){};
    virtual void test(){std::cout << "test da Derivata_2\n";};
};
class Derivata_Mutabile: public Base_ABC {
public:
    Derivata_Mutabile(Base_ABC *based_on){_based_on = based_on;};
    void cambiaBase(Base_ABC *based_on){ delete _based_on; _based_on =
based_on;};
    virtual void test(){_based_on->test();};
    //Qui ci vuole il BIG3
private:
Base_ABC *_based_on;
};
class Derivata_Ultima : public Derivata_Mutabile {
public:
    Derivata_Ultima(Base_ABC* based_on):Derivata_Mutabile(based_on){};
    void eseguiTest(){ this->test();};
};
int main(){
//Dichiarazione dell'oggetto "testami" scegliendo sia la classe
dell'oggetto che la classe da cui ereditare
Derivata_Ultima testami(new Derivata_1());
testami.eseguiTest(); // Derivata_1::test
// Cambio di classe base da usare
testami.cambiaBase( new Derivata_2());
testami.eseguiTest(); // Derivata_2::test;
}
-----------------------------------------------------------------------------------------------
In questo modo però c'è un'istanza duplicata della Base_ABC (Quella
per la base della classe Derivata_Mutabile e quello della base per
Derivata_1 o Derivata_2 usata all'interno di Derivata_Mutabile), ma
essendo ovviamente una ABC non è un problema, ma questo approccio
impone il limitedi ereditare il Mutabile direttamente da una ABC.
Spero di non aver dimenticato nulla o sbagliato nulla per potermi far
capire meglio con questo esempio.
Saluti


Sarò duro ma non capisco... Nel tuo secondo caso, per eliminare la
seconda classe non basta accorpare Derivata_Mutabile e Derivata_Ultima
(che infatti fanno praticamente la stessa cosa)?
Ciao!

 Ciao!
ciao e grazie dell'interessamento...


Se l'esempio è calzante allora aveva ragione logicmind: la classe Mail
è Cartacea *o* Elettronica, quindi anche logicamente non si tratta di
una relazione di ereditarietà. La Mail *ha* un supporto, cartaceo o
elettronico che sia..
Ciao!

 Derivata_1 o Derivata_2?
No.
Il C++ non supporta la definizione dinamica delle classi, e dichiarare 
le superclassi di una classe fa parte della definizione della classe. In 
altre parole, in ogni programma C++ l'insieme delle classi esistenti in 
tale programma � definito in fase di compilazione, e per ogni classe, 
oltre ad essere definiti i membri dalla classe stessa, sono definite 
tutte le sue superclassi con i loro membri.
Questo ovviamente non vuole dire che non si possa fare elegantemente 
quello di cui hai realmente bisogno, per esempio con il design pattern 
Strategy.
-- 
Carlo Milanesi
http://carlomilanesi.wordpress.com/