[ccode]
class CBrush
{
public:
void Draw(); // Definition of this function will be discussed.
// Paints the picture.
private:
bool m_IsInUse;
// Tells if the brush is currently in use (Drawing).
CPainter* m_Painter;
// The painter that uses this brush. NULL if none.
};
class CPainter
{
public:
void Draw()
// Causes the painter to draw.
{
if(m_Brush)
{
m_IsDrawing = true;
m_Brush->Draw();
}
}
bool IsDrawing();
// Tells if the Painter is currently drawing.
private:
bool m_IsDrawing;
// Tells if the the paiter is currently painting.
CBrush* m_Brush;
// The brush this painter uses. NULL if none.
};
[/ccode]
When a painter holds a brush and starts to CPainter::Draw() then the
Brush::IsInUse is obviously needs to change to 'true' since it is in
use. However, since Brush is a different class Painter has to call
some public function to effect the brush, the function is
CBrush::Draw(). However, what if someone else activates the
CBrush::Draw()? The function is public and if it runs the result can
be disastrous - The brush (if it has a painter) will be "painting" but
its owner, the painter will not know about it, CPainter::IsDrawing()
in this case will be still 'false'. Here are the possible solutions I
can see for that problem:
1) Making double check:
In this case the CBrush::Draw will be difined in the following way:
[ccode]
void CBrush::Draw()
{
if(m_Painter && m_Painter->IsDrawing())
m_IsInUse = true;
else
{
m_Painter->Draw();
return;
}
}
[/ccode]
Pros: We solve the situation here by causing the CBrush::Draw() to
check if it was called before CPainter::Draw() and if did then it
would call the CPainter::Draw() first.
Cons: The way works well in most of the situations but sometimes it
can be annoying as it can be somewhat hard to tell from the second
function what exactly changed and to check it and can cause unwanted
changes in one of the classes.
2) Private and friends:
That way I make CBrush::Draw private in the Brush class and let the
CPainter class be a friend of CBrush, that way the CBrush::Draw()
picture will look like this:
[ccode]
void CBrush::Draw() //private
{
if(m_Painter)
m_IsInUse = true;
}
[/ccode]
Pros: That way everything is safe because only CPainter can access
CBrush::Draw() and there is no risk that someone else will do it.
Cons: That way I give the CPainter ALL the access to CPaint while it
is fairly safe it means that the CPainter will need to know all the
CBrush content and be careful not to mess with some other private data
CBrush.
3) Dismissing the problem:
That way I'll come from a more logical point of view, why to defend
CBrush::Draw if no one can access in the first place? If the Painter
won't return a reference of Brush or only returns const reference then
no one can use CBrush::Draw().
[ccode]
void CBrush::Draw() //public
{
if(m_Painter)
m_IsInUse = true;
}
[/ccode]
Pros: Safe - No one can access CBrush but the one who has its pointer
- CPainter.
Cons: But other classes can still create CBrush, assign it to CPainter
and ruin the whole plans in some other class. Also, is it right at all
to make an imperfect function public that running it may cause
troubles?
What do you think?
I think that it's one of two: either it's bad design and has to be
re-approached, or it's a bad example and you have to find a better
one to make your point.
Painter paints. Brush doesn't paint. It gives off colour. From
the world point of view someone of the two has to come first. When
I walk down the street and see somebody working on a sketch or
a painting, I see the person, not the instrument. See what I mean?
Painter::paint()
{
picture.coordinates() = currentbrush.location();
picture.receivestroke(currentbrush.colour(), currentbrush.width());
// repeat if needed
}
IMHO, there is never a need to call Brush::paint, or there is no
such method at all.
Victor
--
Please remove capital A's from my address when replying by mail
"Vitaly Belman" <vit...@bigfoot.com> wrote in message
news:47367956.01071...@posting.google.com...
---
Vitaly Belman
ICQ: 1912453
"Mike P." <nom...@nomail.com> wrote in message news:<Rxc57.469$2Y.3247@NewsReader>...
---
Vitaly Belman
ICQ: 1912453
"Mike P." <nom...@nomail.com> wrote in message news:<dAh57.779$2Y.7971@NewsReader>...