Re: Ok --- *enough* with the private virtual functions...
Carlos Moreno wrote:
And that's it --- I'm as of now sick and tired of *not
understanding*
this thing with private virtual functions... It was a *very long
time* ago that this was brought to my attention, and despite my
asking at the time, and the best effort and best intentions of all
who tried to
help me, I don't think I got it... Not even close!!!
What I *think* is the deal with this, is that instead of doing:
class B
{
public:
virtual void f();
};
class D : public B
{
public:
virtual void f();
};
I should do:
class B
{
public:
void f() { p_f(); }
private:
virtual void p_f();
};
class D : public B
{
private:
virtual void p_f();
};
I see how the above works --- but the thing is, I see it as having
the same effect as the first option (with the public virtual f() );
am I getting it wrong? (that is, is it a different thing that's
done as a recommended practice?), or maybe it is that I'm not seeing
some bad things that can happen with the first case that can not
happen with the second as a consequence of not having public virtual
functions?
The point of polymorphism is that it shouldn't matter to a user of (a
reference to a) B whether a B is really a B or something more
specific.
With the first declaration, you're telling the person calling B::f()
that that B reference you gave him may actually not reference a B,
and that the implementation of f() that he's calling may be different
from the implementation of B::f(), and maybe even that it may do
something other than X, which is what B::f() would do.
That is exactly what he was trying not to think about. The message you
should be sending with this interface is "There's something called a
B, and if you call B::f(), then X will happen to it." No more, no
less.
If there are actually different kinds of B's requiring different
implementations of f() to achieve X, then you might decide to use
derivation and polymorphism in your implementation. But this use of
polymorphism is an implementation issue, and as such it shouldn't
affect the public interface of B.
Hence the second solution, where you tell the user of a B only that
there is a member function f() that will do X to that B. No more, no
less. Which gives the user of that B the chance to, in the spirit of
polymorphism, remain happily oblivious to the complexities of
different kinds of Bs.
So, in the second case my code using a B will look like this:
// get me a B, or some derived class
B * b = get_me_a_B();
// do something to b depending on its dynamic type
b->f();
While in the second case I can write
// get me a B
B * b = get_me_a_B();
// do X to b
b->f();
Your confusion probably stems from the fact that this code is
identical if you leave out the comments. What you missed is the
conceptual difference.
Lourens
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]