Newsgroup: it.comp.lang.c++
Titolo: Breve esercizio

Salve
sarei curioso di vedere le vostre soluzioni al seguente esercizio:
"Si definiscano due classi, ognuna con un membro static, in modo che la
costruzione di ognuno dei due membri statici comporti un riferimento
all'altro. In quali casi reali potrebbero apparire costrutti di questo
tipo? Come si possono modificare queste classi per eliminare le mutue
dipendenze nell'ordine d'invocazione dei costruttori?"
Vorrei che la risposta fosse strettamente attinente alla richiesta
dell'esercizio:
1. il caso deve essere "ragionevolmente reale"
2. per eliminare le dipendenze devono essere modificate le classi
contenenti i membri statici.

 contenenti i membri statici.
Non sono sicuro di aver compreso bene il problema, in particolare il 
significato di "caso ragionevolmente reale".
Comunque, se ho capito  bene, ecco un programma che manifesta il problema:
   class C1 { public: static int m; };
   class C2 { public: static int m; };
   // Scambiando l'ordine delle due righe seguenti,
   // si ottengono risultati diversi.
   int C1::m = C2::m + 1;
   int C2::m = C1::m - 1;
   #include <iostream>
   using namespace std;
   int main()
   { cout << C1::m << " " << C2::m << endl; }
Ed ecco un modifica al suddetto caso, con la quale C1::m viene sempre 
inizializzata a 1 e C2::m viene sempre inizializzata a 0, qualunque sia 
l'ordine in cui sono definite tali variabili:
   class C1 {
   public:
     static bool initialized;
     static int init_m() {
       initialized = true;
       return 1;
     }
     static int m;
   };
   class C2 {
     static int init_m() {
       if (! C1::initialized) C1::m = C1::init_m();
       return C1::m - 1;
     }
   public:
     static int m;
   };
   bool C1::initialized;
   int C1::m = C1::init_m();
   int C2::m = C2::init_m();
   #include <iostream>
   using namespace std;
   int main()
   { cout << C1::m << " " << C2::m << endl; }
-- 
Carlo Milanesi
http://carlomilanesi.wordpress.com/

Grazie. C'ï¿œ solo una cosa che mi fa pensare che la soluzione che hai 
proposto non soddisfi appieno la richiesta dell'esercizio, cioï¿œ che in
 >   int C1::m = C1::init_m();
non si piï¿œ referenzi/usi C2::m. In effetti non si capisce bene se la 
rottura della mutua dipendenza implichi che un costruttore non possa 
riferirsi all'altro membro statico in qualche modo.
Io avevo pensato a una cosa tipo questa, dimmi che ne pensi. Forse ï¿œ 
inutilmente complicata, ma volevo stare nell'esercizio. Come vedrai, il 
membro statico Her_lib usa His_lib e viceversa. L'ordine di definizione 
dei due membri statici puï¿œ variare, a patto che il primo membro statico 
ad essere definito abbia, come argomento che rappresenta un riferimento 
all'altro membro, un valore 0.
#include <iostream>
#include <string>
using namespace std;
class His_lib;
class Her_lib {
public:
     Her_lib(string user_name, His_lib* lib);
     void init(His_lib* lib);
     void post_init(His_lib* lib);
     string get_user_name() {
         return _user_name;
     };
     bool do_post_init;
private:
     string _user_name;
     His_lib* _lib;
};
class His_lib {
public:
     His_lib(string user_name, Her_lib* lib);
     void init(Her_lib* lib);
     void post_init(Her_lib* lib);
     string get_user_name() {
         return _user_name;
     };
     bool do_post_init;
private:
     string _user_name;
     Her_lib* _lib;
};
void Her_lib::init(His_lib* lib) {
     _lib = lib;
     cout << get_user_name() << "::Her_lib is using " << 
lib->get_user_name() << "::His_lib\n";
};
void Her_lib::post_init(His_lib* lib) {
     cout << "Completing " << get_user_name() << "::Her_lib 
initialization...\n";
     init(lib);
}
void His_lib::init(Her_lib* lib) {
     _lib = lib;
     cout << get_user_name() << "::His_lib is using " << 
lib->get_user_name() << "::Her_lib\n";
};
void His_lib::post_init(Her_lib* lib) {
     cout << "Completing " << get_user_name() << "::His_lib 
initialization...\n";
     init(lib);
}
Her_lib::Her_lib(string user_name, His_lib* lib) : /* pre-init */ 
_user_name(user_name), do_post_init(false) {
     if (lib) {
         init(lib);
         if (lib->do_post_init)
             lib->post_init(this);
     } else {
         cout << get_user_name() << "::Her_lib initialization deferred\n";
         do_post_init = true;
     }
}
His_lib::His_lib(string user_name, Her_lib* lib) : /* pre-init */ 
_user_name(user_name), do_post_init(false) {
     if (lib) {
         init(lib);
         if (lib->do_post_init)
             lib->post_init(this);
     } else {
         cout << get_user_name() << "::Her_lib initialization deferred\n";
         do_post_init = true;
     }
}
class A {
public:
     static Her_lib her_lib;
};
class B {
public:
     static His_lib his_lib;
};
Her_lib A::her_lib("class A", 0);
His_lib B::his_lib("class B", &A::her_lib);
int main(int argc, char** argv) {
     return 0;
}
Carlo Milanesi ha scritto:
