Newsgroup: it.comp.lang.c++
Titolo: ancora organizzazione del codice

Supponiamo di avere due classi A e B, e i relativi file A.cpp, A.h, 
B.cpp e B.h. Supponiamo inoltre di avere due lunghe funzioni fA ed fB 
che si prestano ad essere membri rispettivamente delle classi A e B, e 
che si appoggiano entrambe alle stesse funzioni f_1, ..., f_n, non usate 
per altri scopi.
La prima idea potrebbe essere quella di creare un file F contenente le n 
funzioni f_i, fA ed fB. Le prime verrebbero dichiarate static, mentre fA 
ed fB sarebbero rispettivamente membri di A e B.
Un difetto di questa scelta può essere che si viola il paradigma <class 
X, X.cpp, X.h>.
Un'altra possibilità consiste nel dichiarare fA ed fB funzioni globali e 
chiamarle in A e B all'interno di due funzioni inline.
La possibilità forse più interessante è invece la seguente:
=== imp.h ===
#ifndef _IMP_INCLUDE_
#define _IMP_INCLUDE_
class A;
class Misc_A
{
	static void fA();
	friend A;
};
class B;
class Misc_B
{
	static void fB();
	friend B;
};
class Misc : public Misc_A,
			 public Misc_B
{};
#endif
=============
== imp.cpp ==
#include "imp.h"
static void f1() {}
static void f2() {}
static void f3() {}
void Misc_A::fA()
{
	f1();
	f2();
	f3();
}
void Misc_B::fB()
{
	f3();
	f2();
	f1();
}
=============
==== a.h ====
#ifndef _A_INCLUDE_
#define _A_INCLUDE_
#include "imp.h"
class A
{
public:
	A() { Misc::fA(); }
};
#endif
=============
==== b.h ====
#ifndef _B_INCLUDE_
#define _B_INCLUDE_
#include "imp.h"
class B
{
public:
	B() { Misc::fB(); }
};
#endif
=============
= main.cpp ==
#include "a.h"
#include "b.h"
int main()
{
 
}
=============
Cosa ne pensate? Troppo laborioso?
Kiuhnm

 #endif
Questo, e l'analogo file "b.h", costringe a ricompilare tutti i moduli 
che usano A o B, quando cambia l'implementazione del costruttore di A o 
di B, o quando cambia il file "imp.h".
Si evitano tali dipendenze spostando l'inclusione di "imp.h" e il corpo 
del costruttore di A in un file di implementazione, che potrebbe 
chiamarsi "a.cpp", e facendo lo stesso per B (in "b.cpp").
Tuttavia, in tal modo il costruttore non e' piu' inline.
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

 Non era' piu' semplice fare cosi'?
[...]
No, hai perso un dettaglio molto importante.
Il metodo era tutto incentrato su quello.
Kiuhnm

 Il metodo era tutto incentrato su quello.
Spiegati.


 Spiegati.
Se una funzione è globale, chiunque può chiamarla.
Supponi che il progetto contenga un sotto-modulo costituito da alcune 
classi (organizzate in vari file) che necessitino l'accesso a funzioni 
comuni. Definendo tali funzioni come globali, si permette l'accesso 
anche a codice non appartenente a questo sotto-modulo. Il mio post 
propone un metodo abbastanza sistematico per evitare ciò.
Dato che possono esserci due o più sotto-moduli, è utile definire vari 
"contesti globali" ai quali possono accedere solo particolari classi.
Nell'esempio, definisco la classe derivata Misc in modo che si possa 
usare direttamente Misc sia nella classe A che nella classe B.
Perché non scrivere MiscA e MiscB? Perché ci sono situazioni in cui si 
avrebbe MiscAC, o MiscACDE, ecc...
Il meccanismo fa sì che qualora, per es., B tenti di accedere ad fA, 
venga segnalato un errore.
Forse dirai che tutta questa costruzione è artificiosa e poco 
interessante, ma ritengo che sia molto utile l'idea di funzioni 
/parzialmente/ globali.
Kiuhnm