Definisco Classe1

codice:
class Classe1
{
  public:
  //costruttore, distruttore, metodi, ecc
  tipo2 getCl1_membro2() const;//restituisce il valore di membro2
  tipo3 getCl1_membro3() const;//restituisce il valore di membro3
  private:
    //tutto quanto serve da dichiarare come private +
   tipo1 cl1_membro1;
   tipo2 cl1_membro2;
   tipo3 cl1_membro3;
}
Poi definisco Classe2

codice:
class Classe2
{
  //costruttore, distruttore, metodi, ecc
  //poniamo che uno dei metodi, detto cl2_metodo1, abbia bisogno di cl1_membro3, senza modificarlo, per fare quello per cui viene definito
  void cl2_metodo1(const tipo3 parametro/*che è il valore di cl1_membro3, + eventuali altri parametri*/);
  private:
    //tutto quanto serve da dichiarare come private +
   tipo4 cl2_membro1;
   tipo5 cl2_membro2;
   tipo6 cl2_membro3;
}
Poi definisco Classe3

codice:
class Classe3
{
  //costruttore, distruttore, metodi, ecc
  //poniamo che uno dei metodi, detto cl3_metodo1, abbia bisogno di cl1_membro2, senza modificarlo, per fare quello per cui viene definito
  void cl3_metodo1(const tipo2 parametro/*che è il valore di cl1_membro2, + eventuali altri parametri*/);
  private:
    //tutto quanto serve da dichiarare come private +
   tipo7 cl3_membro1;
   tipo8 cl3_membro2;
   tipo9 cl3_membro3;
}
Mi vengono in mente le seguenti opzioni:

  • prima opzione

quando richiamo il metodo in questione, faccio
codice:
Classe1 oggetto1;
Classe2 oggetto2;
Classe3 oggetto3;
oggetto2.cl2_metodo1(oggetto1.getCl1_membro3());
oggetto3.cl3_metodo1(oggetto1.getCl1_membro2());
  • seconda opzione


Evitando di passare il parametro alla funzione, potrei memorizzare sia in Classe2 che in Classe3 un puntatore (eventualmente smart-pointer?) a Classe1, in modo che all'interno del metodo possa richiamare addirittura il metodo di Classe1 senza dover passare il parametro alla funzione. Diventerebbe una cosa del genere

codice:
Classe2
{
   //quanto definito prima
  void cl2_metodo1(/*eventuali altri parametri*/);//il parametro viene  richiamato all'interno del metodo facendo  puntatoreAClasse1->getCl1_membro3()
  private:
    Classe1* puntatoreAClasse1;
}
codice:
Classe3
{
   //quanto definito prima
  void cl3_metodo1(/*eventuali altri parametri*/);//il parametro viene richiamato all'interno del metodo facendo puntatoreAClasse1->getCl1_membro2()
  private:
    Classe1* puntatoreAClasse1;
}
  • terza opzione

definisco in Classe1 come friend i metodi di Classe2 e Classe3.



Arrivo alle domande:
  1. Quale delle tre opzioni è ottimale? Oppure nessuna delle tre è ottimale e ciascuna ha un proprio ambito in cui è meglio?
  2. L'istanza di Classe1, potrebbe non essere stata ancora creata (nel programma verranno dichiarati i puntatori a Classe1, Classe2 e Classe3, e istanziati all'occorrenza), mentre le relative istanze di Classe2 e Classe3 potrebbero essere già state create (oppure andare fuori scope prima di Classe2 e Classe3): come gestire questo aspetto?
  3. gli smart-pointer potrebbero dare una mano a gestire questa verifica di esistenza o meno di Classe1 quando vengono richiamati i metodi di Classe2 e Classe3? Ad esempio, dichiaro Classe1 come shared_ptr, mentre il dato membro di Classe2 e Classe3 sarà un weak_ptr, come ipotizzato qui ?