I`m designing a series of classes that are responsible for creation of a lego-style (well, sort-of) 3D meshes. The basic building block of each mesh is a Box. There could be well over 1000 of these Boxes in each 3D mesh.
However, my following design looks dirty to me since I had to add several "friend class" lines to compile it. How can I clean it and make it less dirty ? Since it`s a relatively common scenario, I`d like to know how to do it properly in the future.
AFAIK, I could have just made the base building block (CBox) public and it would get me rid of "friend class" declarations. But would it really be dirty, if this CBox is really just a simple basic building block ? It could even be a "struct"
Another alternative would be specifying getter/setter methods which would just clutter the interface, so I scrapped this idea.
I`ve had a heated debate with the colleagues on this one and it seems that everybody considers "cluttered/dirty" in a different way.
On the other hand, I personally think, that this is one of the proper uses of "friend" keyword, since it`s 100% sure that only relevant classes get access to this base building block, thus they can`t break things up.
What do you think ?
// Forward declarations
class CScene;
// Mesh class
class CMesh
{
private:
friend class CScene;
class CBox
{
friend class CMesh;
friend class CScene;
class CColor
{
friend class CBox;
D3DCOLOR RGBValue;
CColor (unsigned char R = 255, unsigned char G = 255, unsigned char B = 255) : RGBValue (D3DCOLOR_RGBA (R,G,B,255)) {};
void Set (unsigned char R, unsigned char G, unsigned char B)
{ RGBValue = D3DCOLOR_RGBA (R,G,B,255); }
};
D3DXVECTOR3 POrigin;
D3DXVECTOR3 PWidth, PDepth, PHeight;
CColor Color;
CBox (D3DXVECTOR3 fPOrigin = D3DXVECTOR3(0,0,0), D3DXVECTOR3 fPWidth = D3DXVECTOR3(0,0,0), D3DXVECTOR3 fPDepth = D3DXVECTOR3(0,0,0), D3DXVECTOR3 fPHeight = D3DXVECTOR3(0,0,0), CColor fColor = CColor ()) : POrigin (fPOrigin), PWidth (fPWidth), PDepth (fPDepth), PHeight (fPHeight), Color (fColor) {};
void Set (D3DXVECTOR3 fPOrigin, D3DXVECTOR3 fPWidth, D3DXVECTOR3 fPDepth, D3DXVECTOR3 fPHeight, CBox::CColor fColor)
{ POrigin = fPOrigin; PWidth = fPWidth; PDepth = fPDepth; PHeight = fPHeight; Color = fColor; };
void Set (D3DXVECTOR3 fPOrigin, D3DXVECTOR3 fPWidth, D3DXVECTOR3 fPDepth, D3DXVECTOR3 fPHeight)
{ POrigin = fPOrigin; PWidth = fPWidth; PDepth = fPDepth; PHeight = fPHeight; };
};
CBox BBox;
vector <CBox> Boxes;
public:
void AddHorizontalBars (int BarsCount, float BarSpacing, D3DXVECTOR3 BarOrigin, float BarWidth, float BarDepth, float BarHeight, CBox::CColor BarCOlor);
void AddVerticalBars (int BarsCount, float BarSpacing, D3DXVECTOR3 BarOrigin, float BarWidth, float BarDepth, float BarHeight, CBox::CColor BarCOlor);
CMesh () { };
~CMesh () { void ReleaseAllMemory (); };
void ReleaseAllMemory () { };
};
// Class for Scene containing all meshes
class CScene
{
private:
vector <CMesh> Meshes; // Array of Scene meshes
void GenerateMeshes ();
public:
CScene () { };
~CScene () { ReleaseAllMemory (); }
void ReleaseAllMemory () { };
};