Newsgroup: it.comp.lang.c++
Titolo: Problema di derivazione classi

Salve a tutti,
	spero possiate aiutarmi in questo problema di ereditarieta'
dato che, come ho gia' detto in un post precedente, e' un po' che non
uso il c++.
Ho due classi che sono in una relazione "has-a" cioe', facendo un 
esempio astratto :
class HardDisk
{.....};
class Computer
{
private:
	HardDisk hd;
};
Quello che voglio fare e' permettere di accedere alle funzioni della
classe HardDisk che sono solo in lettura delle proprieta' e filtrare 
invece le funzioni in scrittura tramite la classe Computer.
Per esempio quello che vorrei fare e':
class HardDisk
{
public:
	long getDimension();
protected:
	int setDimension(long);
private:
	long dimension;
};
class Computer: public HardDisk
{
public:
	HardDisk getHardDisk (int index){...};
	int setHD_Dimension_Filtered (int index, char* password){...};
private:
	HardDisk raid[4];
	char* Admin_pwd;
};
Quello che voglio e' che non si possa accedere a:
HardDisk::setDimension() 
tramite la chiamata:
(getHardDisk(int)).setDimension(long);
e vi sia l'obbligo di passare per setHD_Dimension_Filtered(). 
Pensate sia corretto questo disegno di classi con l'ereditarieta'
pubblica o c'e' un modo piu' efficiente e/o pulito per farlo ?
Grazie in anticipo.
Ciao Paolo

 e vi sia l'obbligo di passare per setHD_Dimension_Filtered().
L'unica è non rendere pubblica la funzione getHardDisk(), mi sembra.
EMG

 Ciao Paolo
Secondo me questo tipo di relazione va reso in uno dei due modi
seguenti:
- Se non hai bisogno di usare oggetti HardDisk direttamente, ma solo
dall'interno di un computer, puoi usare una inner class:
class Computer
{
public:
   HardDisk getHardDisk();
   int setHD_Dim(int, char*);
//....
private:
   struct HardDisk
   {...}
   HardDisk hd;
};
- Se invece devi poter usare degli HardDisk indipendentemente dal fatto
che siano o meno in un Computer, puoi dichiarare la classe Computer
friend di HardDisk:
class HardDisk
{
  friend class Computer;
public:
  int getDimension();
  //...
private:
  int setDimension(int);
  //...
};
class Computer
{
public: 
 //...
 int setHD_Dim(//...);
private:
  HardDisk hd;
  //...
};
In questo modo, puoi accedere ai campi privati di HardDisk dalla classe
Computer, ottenendo cosi' un controllo dell'accesso.
Usare l'ereditarieta' in questo caso non mi sembra la scelta migliore,
in quanto logicamente un computer non e' una specializzazione di un
hardDisk.
Spero di essere stato di aiuto
Ciao,
Alberto Griggio


Usa la derivazione solo quanto hai una relazione di tipo IS-A.
Non mi sembra che un computer sia un HardDisk.
Sent via Deja.com
http://www.deja.com/

hardDisk.
Grazie, e' proprio quello che cercavo, non avevo pensato a delle classi
friend. In effetti, come suggerito anche da altri, in una relazione
"has-a" l'ereditarieta' non e' logicamente attinente.
Ciao Paolo

};
La derivazione (pubblica) in questo contesto mi sembra
un errore.
Semplicemente dovresti utilizzare il contenimento e mettere in
Computer delle funzioni di forwarding. In alternativa potresti
utilizzare l'ereditarieta` privata ed esportare solo i metodi di
HardDisk che ti interessano (io sono cmq piu` propenso al contenimento).
Paolo
--
Paolo Marotta
Duck Communication Entertainment s.r.l.
Largo Arenula, 11 - Roma
http://www.duckce.com
p.ma...@duckce.com
-- 
Posted from 
HA-server-a.cs.interbusiness.it
 [151.99.250.31] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

"has-a" l'ereditarieta' non e' logicamente attinente.
Le classi friend a mio avviso sono da evitare, tranne nei casi in cui
sono realmente indispensabili. Il tuo del resto é un esempio classico
che si risolve con una semplice operazione di contenimento.
class contenuta
    {
    /*...*/
    };
class contenitore
    {
    public:
        contenuta obj;
    /*...*/
    }
Ovviamente dichiarando un dato membro di tipo contenuta le funzioni
membro di contenitore non possono accedere ai dati ed alle funzioni
membro private o protette dell'istanza della classe contenuta, percui
per i suddetti dati membro la classe contenuta dovrà prevedere delle
apposite funzioni membro pubbliche che restituiscono i dati della
classe. Spero che adesso avrai le idee un pò più chiare.
Lavinia
WINWORD.EXE - ERRORE DI APPLICAZIONE
l'istruzione a "0x3017ff27"ha fatto riferimento alla
memoria a "0x02a3143c".La memoria non poteva essere 'read'.

classe. Spero che adesso avrai le idee un pò più chiare.
Non penso vada bene questa soluzione; io voglio che dal programmma si
possa accedere ad alcune funzioni di sola lettura dei dati della classe
contenuta, e da contenitore si possa accedere anche alle funzioni di
scrittura dei dati della classe contenuta.
Dovendo dichiarare pubbliche le funzioni di scrittura necessarie alla
classe contenitore, queste sarebbero visibili a tutto il programma.
Il mio uso di friend non servirebbe a scrivere direttamente nei dati
(altrimenti addio information hiding) ma solo ad accederealle funzioni
di scrittura dei dati della classe
Ciao
Paolo

 scrittura dei dati della classe contenuta.
Non ho seguito il thread, quindi non escludo che i suggerimenti che ti sto
per proporre non siano applicabili.
Anzichè restituire un riferimento all'oggetto interessato, puoi definire
un'opportuna interfaccia per l'accesso di sola lettura e utilizzarla
derivando la classe interessata da quell'interfaccia. In alternativa puoi
creare un opportuna classe proxy e restituire un'instanza di quella, nel
caso tu non voglia o non possa modificare la definizione della classe
originale. Due esempio pratici:
Nel caso tu possa e voglia modificare la definizione la classe interessata
puoi procedere così:
 
 struct readable_HardDisk {  // interfaccia sola lettura
  virtual int getA() const = 0;
 };
 struct HardDisk : public readable_HardDisk
 {
    int getA() const { return 1; }
    void setA(int i) { /* ... */  };
 };
 struct Computer
  {
    HardDisk   hd_;
    const readable_HardDisk& getHardDisk() const
    {  return hd_; }
  };
Nel codice client:
  Computer comp;
  const readable_HardDisk& hd = comp.getHardDisk();
  int a = hd.getA();
Se invece hai una class HardDisk già pronta, che per qualche ragione tu
non vuoi o puoi alterare:
 struct HardDisk {  
    void setA(int i); 
    int getA() const;
 };
Definiamo una classe che esponga solo un metodo getA() e deleghi la sua
implementazione a un oggetto HardDisk:
 
  struct HardDisk_px
  {
    const HardDisk* ptr_;
    HardDisk_px( const HardDisk* ptr) : ptr_(ptr) { }
    int getA() const { return ptr_->getA(); }
  };
  struct Computer
  {
    HardDisk   hd_;
    HardDisk_px getHardDisk() const 
    {  return HardDisk_px( &hd_); }
  };
Nel codice client:
  Computer comp;
  HardDisk_px hd = comp.getHardDisk();
  int a = hd.getA();
Max
 

Non vedo perche' farla cosi' complicata...
Abbiamo questi "requirements" :
1) Computer ha un hard-disk e puo' modificarlo
2) I client di Computer possono accedere al suo HardDisk senza
   modificarlo.
La soluzione piu' semplice e':
class Computer
{
   ...
   HardDisk  theHardDisk;
public:
   ...
   const HardDisk & hardDisk() const;
};
a questo punto, Computer puo' accedere liberamente al suo HardDisc.
I client di Computer possono ottenere un const reference all'HerdDisk.
Senza bisogno di ereditarieta', proxy e altre classi intermedie...
Saluti.
Fabio


Senza bisogno di ereditarieta', proxy e altre classi intermedie...
Grazie per la risposta, mi potresti solo spiegare quel const a destra di
const HardDisk & hardDisk() const; a cosa serve?.
Paolo

const HardDisk & hardDisk() const; a cosa serve?.
indica che quella funzione non può modificare le variabili membro di
un oggetto nè richiamare funzioni membro non-const; può tuttavia
modificare il valore di variabili membro dichiarate mutable; se si ha
un oggetto dichiarato const, si possono richiamarne solo i metodi
const
class ABC {
	mutable int x;
	int y;
public:
	ABC(): x(0),y(0) { }
	int f() const { x++; return y; }
};
in questo caso f() può modificare x perchè è dichiarata mutable, ma
non può modificare y (anche se può leggerne il valore).
Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.44, higher than 97% of all previous test takers.
Visual Basic 5: 3.06, higher than 77% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688