Newsgroup: it.comp.lang.c++
Titolo: [?] protected: troppo protetto??

Ciao,
    non riesco a capire il motivo per cui mentre č possibile richiamare da
una funzione propria di una classe derivata un elemento protected della
classe base non e' possibile fare lo stesso tramite un puntatore alla classe
base .... meglio un esempio:
class ABase{
    protected:
        int a;
};
class B:public ABase{
    public:
        void f(ABase* pt);
};
void B::f(ABase* pt)
{
    pt->a=0;   /* Errore: non si puņ accedere all'elemento protetto
                        di ABase tramite il puntatore anche se mi trovo in B
                        che ha le autorizzazioni a leggere gli elementi
protetti
                        di B*/
    a=0;        /*    B puņ accedere agli elementi protetti di A */
}
Mi piacerebbe sapere quale sia il motivo di questa scelta implementativa del
C++.
Un modo semplice e mi sembra indolore per fare l'operazione, che a me sembra
lecita, e' quello di utilizzare una f() virtuale e per ciascuna classe
derivata fare un cast del puntatore del tipo ((B*)pt) ed accedere
all'elemento protetto ma non mi sembra "pulito". Perchč mi viene impedito
nel modo pulito ???
    Ciao e grazie
        Carlini Alessio

 ha scritto nel messaggio
news:8pkoqq$m4i$1...@nslave1.tin.it...

Stai facendo un poco di confusione.
L'uso corretto di protected č:
  void B::f(ABase* pt)
  {
     a = 0;    // puoi solo accedere alla a di QUESTA istanza
  }
Se vuoi accedere a pt->a devi dichiarare B friend di ABase.
Se fosse permesso quello che vuoi, sarebbe un bel problema!
Manlio Perillo

 Se fosse permesso quello che vuoi, sarebbe un bel problema!
E' questa la domanda!
Mi potresti fare qualche esempio di problema che ne deriverebbe???



Il fatto è che in questo modo se io derivo una classe da
ABase e passo un suo puntatore a B::f(), mi ritrovo con
un suo membro modificato 'a mia insaputa'.
Questo potrebbe non essere un problema in un piccolo progetto,
ma il C++ è stato progettato per i grandi progetti e qui
si potrebbero avere problemi.
Purtroppo non so farti un esempio concreto.
Manlio Perillo

base ....
Una cosa che non molto nota e' che alle parti dichiarate "protected"
si puo' accedere solo tramite un puntatore di tipo della stessa
classe. In particolare una istanza non puo' accedere ai membri
protected di un'altra usando puntatori di tipo 'puntatore a base'.
La motivazione CREDO che sia che classi diverse derivate da una
stessa base potrebbero fare un uso diverso delle parti 'protected'.
Non avrebbe quindi senso accedere a queste parti tramite un
generico puntatore a base (visto che il significato del membro
sarebbe ignoto).
Una cosa che ovviamente funziona e':
   class Base
   {
     ...
     protected:
       int x;
   };
   class Derived : public Base
   {
     ...
     void Fun1(Derived *other)
     {
       other->x++;  // Accede al membro protected di
                    // un'altra istanza
     }
     ...
   }
visto che in questo caso essendo la classe la stessa
il significato e' chiaro. E' anche possibile accedere
a membri protected di altre istanze tramite puntatori
a classi derivate dalla classe corrente.
A rigore di logica quest'ultima parte non mi convince
molto: se una derivata puo' cambiare il significato
logico di un membro protected allora accedere al membro
di una derivata non dovrebbe essere ammesso per lo
stesso motivo (che ne sa la base del significato del
membro ?)
Una cosa che mi ha abbastanza colpito e' che dichiarare
un costruttore protected rende impossibile per chiunque
(derivate incluse) istanziare la classe base.
Prendi la spiegazione con beneficio di inventario,
personalmente non amo i design che usano 'protected' 
e non sono certamente un esperto della cosa :)
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 Se vuoi accedere a pt->a devi dichiarare B friend di ABase.
Ehm... credo ci sia un po' di confusione sull'argomento: l'unità di
protezione in C++ è la *classe* e non l' *oggetto*! Questo significa che un
oggetto conosce come è fatto un altro oggetto della stessa classe (è ovvio)
e perciò può modificare anche i membri privati di un altro oggetto, purchè
della stessa classe.
In ogni caso, i data-members dovrebbero *sempre* essere private e mai
protected o public. Questo per mantenere l'information hiding e nascondere
l'implementazione di una classe.
Faccio notare che il seguente codice funziona:
class c {
public:
    void f( c* item ) { item->x = 10; }
private: /* o protected: */
    int x;
};
Saluti
Daniele.

}
B puo` accedere alla sua "copia" di a, ma non a quella
di un'altra classe (bisognerebbe che B fosse dichiarata friend)..
Paolo
-------------------------------------------
  Paolo Marotta
 
http://web.tiscalinet.it/paolo_marotta/
-------------------------------------------

Mi potresti fare qualche esempio di problema che ne deriverebbe???
Non e` questione di problema, ma di diverso significato di protect e
friend. Il primo permette ad una classe derivata di accedere a
certi membri della classe base (e solo della classe base) *che
eredita*, il secondo di accedere a tutti i membri di una qualsiasi
classe (non c'e` ereditarieta`).


Grazie per il tuo contributo, quantomeno hai capito il problema :)
Di fatto anche io ho dovuto ripiegare eliminando la parte protetta
(protected) inserendo delle funzioni pubbliche che suppliscono alle mancanze
ma la cosa non mi piace molto ... mi domando infatti se sia possibile che
l'uso di elementi protected sia così limitato da essere più fastidioso che
altro!
Sono più propenso a credere che sia io a commettere qualche "errore" nel suo
utilizzo e/o nella progettazione del software!!
Cercando cercando prima o poi capirò che ci devo fare co sto protected :)
Ciao e grazie di nuovo
        Carlini Alessio

 Cercando cercando prima o poi capirň che ci devo fare co sto protected :)
Membri protetti infatti non andrebbero quasi mai usati...
Per i data-member: sempre privati.
Per le function-member: pubblici o privati.
Daniele.

utilizzo e/o nella progettazione del software!!
Probabilmente un errore di design... non pensare in termini di
operazioni sui data member, pensa in termini di servizi (di alto
livello) che una classe deve fornire alle altre.
