Newsgroup: it.comp.lang.c++
Titolo: newbie in crisi con ereditarieta' e "protezione"

ciao a tutti da un newbye del c++ (per forza causa progetto
universita'!)
il mio problema riguarda l'ereditarieta'; allora:
ho una classe base (non istanziabile) con un vettore "protected":
class Base{
protected:
	vector<elem_type> prot;
};
poi ho tante classi derivate in cui ho anche un vettore privato:
class DerivedX: public Base{
private:
	vector<elem_type> priv;
};
class DerivedY: public Base{
private:
	vector<elem_type> priv;
};
ovviamente oltre a tutto il resto.
Ho bisogno di alcune funzioni che utilizzano sia il vettore privato che
quello protetto.
void metodoZ{
	//uso i vettori priv e prot
}
Devo definirlo ed implementarlo in ogni classe Derivata?? mi sembra uno
spreco!
Penso che sicuramente ci sara' una soluzione piu' elegante ma non me ne
viene in mente nessuna!
Potete aiutarmi? (sempre che mi sia spiegato decentemente e non abbia
detto troppe cavolate!)
Thanks!
Sent via Deja.com 
http://www.deja.com/
Before you buy.

 
Per evitare di riscrivere l'implementazione del metodo che usa prot e
priv, io adotterei questa tecnica (già suggerita in altre occasioni).
Prima creiamo questa classe template con l'implementazione che ci serve.
 template < class Derived >
 class common_impl
 {
     protected:
     int funzione_che_usa_prot_e_priv()
     {
       Derived& thisref = static_cast<Derived&>(*this);
 
        int sz1 =  thisref.prot.size(); 
        int sz2 =  thisref.priv.size();
        // resto dell'implementazione....
     }
 };
Quindi deriviamo le nuove classi in questo modo:
 class DerivedX: public Base, public common_impl< DerivedX >
 {
     vector<int>	prot;
     typedef common_impl<DerivedX>	common_impl_type;	 
     friend common_impl_type; // così common_impl<DerivedX>
                              // ha visibilità su prot e priv
    public:
    int funzione_che_usa_prot_e_priv() 
    { 
      return common_impl_type::funzione_che_usa_prot_e_priv() ;
     }
 };
Max





Questa prassi e' nota come 
polimorfismo.


E' una cosa molto lunga e complicata che faresti 
meglio a studiare.


In poche parole un puntatore alla classe base puo' 
accedere a qualsiasi(usando qualche trucco) elemento della classe 
derivata.


Questo e' il massimo che ti possa dire per e-Mail 
ora devi studiare il polimorfismo e l'uso dei puntatori nell'ereditarieta' 
multipla..



}
'private' significa che si tratta di qualcosa di interno ad una
classe e nessuno (a parte la classe stessa e i friend) e'
autorizzato ad accedere alla cosa.
Se un metodo che non e' specifico della classe derivata (ma e'
ad esempio un metodo della classe base) deve accedere al
vettore allora c'e' un controsenso logico a dire che il vettore
e' private.
Se il problema e' che tutte le classi derivate che cerchi sono
"fatte con lo stampino" probabilmente si tratta di un lavoro per
i template (o in casi piu' complessi per un generatore di codice).
Probabilmente aggiungere un po' di contesto potrebbe aiutare
a comprendere quale e' il vero problema.
Andrea

polimorfismo e l'uso dei puntatori nell'ereditarieta' multipla..
L'ereditarieta' multipla centra ancora meno.
Andrea


ciao Andrea, grazie per l'aiuto...questo e' il succo del progetto
(molto teorico e molto poco pratico!) che devo svolgere:
tale progetto si basa su una struttura di classi in gerarchia mediante
ereditarieta' (non multipla). Tale gerarchia e' l'implementazione
di "Permessi" su risorse eterogenee: grafica, db, dischi, socket,
ecc... ecc...
ad ogni permesso e' associata una lista di azioni consentite; per
esempio un permesso "grafico" potrebbe consentire la creazione,
distruzione di finestre, un permesso "socket"  creare e terminare
connessioni, ecc... ecc... le azioni di un permesso sono in parte
protected (e quindi ereditabili da Permessi derivati da questo) e in
parte private (necessarie solo al permesso stesso). se pero', per
esempio, voglio una lista completa devo accedere ai due vettori priv e
prot e qui sorge il problema... spero di essere stato chiaro!
ciao by giuseppe


ciao by giuseppe
Mi sembra che in questo approccio il downcasting sia usato in modo
essenziale. In particolare chi manipola un "permesso astratto" dovra'
sempre fare un cast prima di poter utilizzare i metodi del permesso.
La cosa non mi piace molto da un punto di vista "oo puro" in
quanto si tratta di un uso abbondante di "code to find code" che
irrigidisce il sistema. Cambiare pero' la cosa comporterebbe un
approccio completamente diverso e credo che questo non sia permesso.
Per la gestione della lista io ho fatto qualcosa di simile in un altro
contesto (elenco punti di controllo in una entita' grafica CAD/CAM);
la soluzione che ho adottato e' stata qualcosa come:
1) La classe base prevede una funzione virtuale che restituisce
   la lista dei punti di controllo (per la base astratta la lista
   restituita e' vuota)
2) Ogni classe derivata chiama prima la generazione dei punti chiave
   della classe base e poi aggiunge alla lista i punti specifici
In codice diventa qualcosa come:
  class Base
  {
    ...
    virtual std::list<Elemento> GetList()
    {
      return std::list<Elemento>();
    }
  };
  ...
  std::list<Elemento> Derived1::GetList()
  {
    std::list<Elemento> l=Base::GetList();
    // Aggiunge elementi specifici derived 1
    l.push_back(...);
    l.push_back(...);
    l.push_back(...);
    return l;
  }
  std::list<Elemento> Derived2::GetList()
  {
    std::list<Elemento> l=Base::GetList();
    // Aggiunge elementi specifici derived 2
    l.push_back(...);
    l.push_back(...);
    l.push_back(...);
    return l;
  }
Io non ho usato container standard (non li conoscevo
ancora) ma bisogna stare attenti che container standard
e polimorfismo non vanno d'accordo. Una soluzione
potrebbe essere il restituire una lista di proxy o di
smart-ptr agli elementi (meglio non puntatori nudi).
Nota che con l'approccio a lista nessuno deve rendere
pubblica la struttura dati in cui mantiene i permessi,
anzi... puo' anche essere che non esista una struttura
simile e che le cose vengano costruite al momento quando
qualcuno le richiede (io usavo questo sistema).
Il singolo elemento della lista potrebbe contenere un
puntatore a chi ha generato l'elemento in modo che
metodi applicati a qualcosa contenuto nella lista
agiscono indirettamente sull'oggetto che li ha generati
(nel mio caso se l'utente modifica la posizione di un
punto chiave l'editor passa la notifica all'entita'
proprietaria del punto chiave).
Spero che quello che ho scritto abbia un senso anche
per te... non ragiono molto bene la mattina presto :)
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 Andrea
grazie per l'aiuto che mi hai dato, tu ed anche gli altri! adesso vedo
qual'e' la soluzione migliore per il mio problema e poi spero di
riuscire a cavarne qualcosa.... anche se veramente qualcosa mi e'
venuto in testa...vedremo! Grazie ancora!
Ciao by Beppe
