 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
tarjei.knapstad@gmail.com Guest
|
Posted: Tue Sep 19, 2006 12:25 am Post subject: Private implementation of public pure virtual |
|
|
The recent thread "Sanity check: public/private" led me to try
something out which unexpectedly succeeded:
/////////////////////////
#include <iostream>
class B
{
public:
virtual ~B() {}
virtual void f() = 0;
};
class D : public B
{
public:
virtual ~D() {}
private:
virtual void f() { std::cout << "D::f()" << std::endl;}
};
int main()
{
D d;
B* p = &d;
p -> f();
}
/////////////////////////
This code compiles (and in the latter case runs and produces the
"D::f()" output) with both Comeau online and gcc 4.0.2. I couldn't find
anything in the standard about this, but I'm surprised that neither
compiler at least warns me about what I'm doing here (IMHO I should get
an error).
I don't see how this code could have any practical use, but would
consider it a bug in both compilers...? (The only practical use would
be for hiding away parts of an interface, but then you've got design
issues plus the fact that this just doesn't work).
Comments?
{ See the FAQ item "When should someone use private virtuals?" currently
at <url:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>.
-mod }
--
Tarjei Knapstad
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Alan Griffiths Guest
|
Posted: Tue Sep 19, 2006 9:57 pm Post subject: Re: Private implementation of public pure virtual |
|
|
tarjei.knapstad (AT) gmail (DOT) com wrote:
| Quote: | The recent thread "Sanity check: public/private" led me to try
something out which unexpectedly succeeded:
....
This code compiles (and in the latter case runs and produces the
"D::f()" output) with both Comeau online and gcc 4.0.2. I couldn't find
anything in the standard about this, but I'm surprised that neither
compiler at least warns me about what I'm doing here (IMHO I should get
an error).
|
The code does precisely what the standard says it should - I don't
understand why you expect an error.
| Quote: | I don't see how this code could have any practical use, but would
consider it a bug in both compilers...? (The only practical use would
be for hiding away parts of an interface, but then you've got design
issues plus the fact that this just doesn't work).
|
It is a reasonable intent to ensure that any usage is through the
interface defined by the base type - and to adopt this design to
prevent use through the creation type. (Another, perhaps more
familiar, way to achieve this is a factory methods with a "hidden"
implementation type.)
That would appear to be a separate issue - and address idioms like NVI.
--
Alan Griffiths
http://www.octopull.demon.co.uk/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
AlbertSSj Guest
|
Posted: Tue Sep 19, 2006 10:14 pm Post subject: Re: Private implementation of public pure virtual |
|
|
| Quote: | I don't see how this code could have any practical use, but would
consider it a bug in both compilers...? (The only practical use would
be for hiding away parts of an interface, but then you've got design
issues plus the fact that this just doesn't work).
Comments?
|
The compiler is right, more this code still works....
class A {
public:
void call_b() { b(); }
virtual void a() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
private:
virtual void b() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
class B : public A {
public:
virtual void b() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
private:
virtual void a() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main() {
A* a = new B();
a->a();
a->call_b();
}
Cause maybe you need to implement a function that you want to accessed
only
from the interface, or you want to implement a private function (the
template method pattern is a pratical example) but the private doesn't
matter anymore.
To me this is perfectly reasonable
struct C : B {
virtual void a() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual void b() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
I used this coupled with anonymous namespaces to hide implementation
details and keep definitions compact.
Changes between public and private give you flexibilty ^^
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Jiang Guest
|
Posted: Wed Sep 20, 2006 8:28 pm Post subject: Re: Private implementation of public pure virtual |
|
|
tarjei.knapstad (AT) gmail (DOT) com wrote:
| Quote: | The recent thread "Sanity check: public/private" led me to try
something out which unexpectedly succeeded:
|
[snip]
| Quote: |
I don't see how this code could have any practical use, but would
consider it a bug in both compilers...? (The only practical use would
be for hiding away parts of an interface, but then you've got design
issues plus the fact that this just doesn't work).
Comments?
|
This issue was discussed here recently, please check
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/ce302b361df108c/d47ec8b39c85ce8d?lnk=st&q=&rnum=19#d47ec8b39c85ce8d
for further details.
Actually the above code is perfect valid according to the current
standard.
But I think you are not along if you feel strange about the above
behavoir.
Sorry but the above faq has litte to do with the OP's problem,
and also IMHO that faq is quite misleading.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Timo Geusch Guest
|
Posted: Wed Sep 20, 2006 8:30 pm Post subject: Re: Private implementation of public pure virtual |
|
|
tarjei.knapstad (AT) gmail (DOT) com wrote:
| Quote: | This code compiles (and in the latter case runs and produces the
"D::f()" output) with both Comeau online and gcc 4.0.2. I couldn't
find anything in the standard about this, but I'm surprised that
neither compiler at least warns me about what I'm doing here (IMHO I
should get an error).
|
This is perfectly valid code - the access specifier and the fact that
the function is virtual are pretty much orthogonal. You can even write
code like this and it'll be standard-compliant:
class foo {
public:
void publicInterface();
private:
virtual bool doSomethingWeDontwantToExpose();
};
class bar: public foo {
private:
virtual bool doSomethingWeDontwantToExpose();
};
| Quote: | I don't see how this code could have any practical use, but would
consider it a bug in both compilers...? (The only practical use would
be for hiding away parts of an interface, but then you've got design
issues plus the fact that this just doesn't work).
|
What do you mean, "it just doesn't work"? Could you elaborate on this?
It actually does have some practical use (although the public/private
one less so) if you want or need to make all functions on the public
interface non-virtual. Sometimes the way functions are called doesn't
allow for the virtual function call mechanism to kick in on the direct
call so you need to squirrel away the virtual mechanism. And once
you're exposing a non-virtual handle-type interface that calls through
to virtual functions, it makes sense to make them private.
It's not a technique that you should use all over the place just
because you can but it's occasionally useful.
Hrmpf. I'm not too hot on this comment - the reasoning smacks a bit too
much of "let's dumb down the language so we don't confused the poor
developers" .
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Yuri Yushchenko Guest
|
Posted: Wed Sep 20, 2006 8:42 pm Post subject: Re: Private implementation of public pure virtual |
|
|
tarjei.knapstad (AT) gmail (DOT) com wrote:
| Quote: | The recent thread "Sanity check: public/private" led me to try
something out which unexpectedly succeeded:
/////////////////////////
#include <iostream
class B
{
public:
virtual ~B() {}
virtual void f() = 0;
};
class D : public B
{
public:
virtual ~D() {}
private:
virtual void f() { std::cout << "D::f()" << std::endl;}
};
int main()
{
D d;
B* p = &d;
p -> f();
}
/////////////////////////
|
Hello!
Its all right with this code.
The point is that compiller performs static check to find out whether
the function "f()" is accessible.
In other words, your object on which the pointer "p" points, has 2
types - a static type and a dynamic type. Static means - type of object
on compilation phase.
Dynamic means type of object in runtime.
Static type of object - is "B".
Dynamic type of object is "D".
So, to check (its compile time check) whether the function is exist and
accessible, the static type of object is used.
And to call this function in runtime, dynamic type is used (since the
function is virtual) - dynamic type of the object is "D" (VTLB pointer
points to VTLB of class "D")
So the behavior is correct from the point of view of C++ standard.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Wed Sep 20, 2006 9:38 pm Post subject: Re: Private implementation of public pure virtual |
|
|
* Jiang:
It concerns the very same issue. Access specifiers and virtuality (the
ability to override) are orthogonal features: one does not affect the
other, at the technical level. The issue is then how these features can
or should be meaningfully mixed at the design level.
| Quote: | and also IMHO that faq is quite misleading.
|
Could you please elaborate on that, so that the FAQ could be improved?
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
tarjei.knapstad@gmail.com Guest
|
Posted: Thu Sep 21, 2006 10:17 pm Post subject: Re: Private implementation of public pure virtual |
|
|
Alf P. Steinbach wrote:
| Quote: | * Jiang:
{ See the FAQ item "When should someone use private virtuals?"
currently
at <url:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>.
-mod }
Sorry but the above faq has litte to do with the OP's problem,
It concerns the very same issue. Access specifiers and virtuality (the
ability to override) are orthogonal features: one does not affect the
other, at the technical level. The issue is then how these features can
or should be meaningfully mixed at the design level.
|
Firs off, thanks to everyone for clearing this up for me.
I was tempted to make the same comment about the FAQ entry not being
related to my question at first, but I see how they relate now given
the fact that virtuality/acess specs are orthogonal.
I agree with others though - I still don't think that entry is very
useful. It starts with saying "Almost never", then goes on to say "just
avoid it to avoid confusion" and ends with "unless there's a compelling
reason to the contrary, avoid private virtuals". What could this
compelling reason be? It basically just says "don't do it" without
giving any rationale beyond avoiding confusion.
Thanks again,
--
Tarjei Knapstad
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
tarjei.knapstad@gmail.com Guest
|
Posted: Thu Sep 21, 2006 10:21 pm Post subject: Re: Private implementation of public pure virtual |
|
|
{ bringing to everybody's attention: the second part doesn't need
to be here since it adds nothing to the discussion. -mod }
Timo Geusch wrote:
| Quote: | tarjei.knapstad (AT) gmail (DOT) com wrote:
snip
I don't see how this code could have any practical use, but would
consider it a bug in both compilers...? (The only practical use would
be for hiding away parts of an interface, but then you've got design
issues plus the fact that this just doesn't work).
What do you mean, "it just doesn't work"? Could you elaborate on this?
|
This had to do with how I originally thought this code would work -
never mind, it doesn't even make any sense to me now :)
| Quote: | It actually does have some practical use (although the public/private
one less so) if you want or need to make all functions on the public
interface non-virtual. Sometimes the way functions are called doesn't
allow for the virtual function call mechanism to kick in on the direct
call so you need to squirrel away the virtual mechanism. And once
you're exposing a non-virtual handle-type interface that calls through
to virtual functions, it makes sense to make them private.
It's not a technique that you should use all over the place just
because you can but it's occasionally useful.
|
Thanks for that explanation.
Regards,
--
Tarjei Knapstad
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Earl Purple Guest
|
Posted: Thu Sep 21, 2006 10:50 pm Post subject: Re: Private implementation of public pure virtual |
|
|
Alf P. Steinbach wrote:
| Quote: |
It concerns the very same issue. Access specifiers and virtuality (the
ability to override) are orthogonal features: one does not affect the
other, at the technical level. The issue is then how these features can
or should be meaningfully mixed at the design level.
and also IMHO that faq is quite misleading.
Could you please elaborate on that, so that the FAQ could be improved?
|
Actually while I agree that it is better to have the virtual methods
protected rather than public it is not for the reason stated in the
FAQ.
The reason it is better for them to be protected is so that a derived
class can invoke as part of its implementation of the function the
method in its super class.
Thus:
class A
{
public:
virtual ~A();
void f() { do_f(); }
protected:
virtual void do_f() = 0;
};
class B : public A
{
protected:
virtual void do_f() { // implementation }
};
class C : public B
{
protected:
virtual void do_f()
{
// do some stuff
B::do_f();
// do some more stuff
}
};
Of course you can change the access specifiers only for those specific
classes that may have another one derive from them and call the base
class behaviour but that means prior knowledge of what may derive from
your class.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Fri Sep 22, 2006 5:44 pm Post subject: Re: Private implementation of public pure virtual |
|
|
Jiang wrote:
| Quote: | Alf P. Steinbach wrote:
* Jiang:
{ See the FAQ item "When should someone use private
virtuals?" currently at <url:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>.
-mod }
Sorry but the above faq has litte to do with the OP's problem,
It concerns the very same issue. Access specifiers and
virtuality (the ability to override) are orthogonal
features: one does not affect the other, at the technical
level. The issue is then how these features can or should
be meaningfully mixed at the design level.
Yes, what you said is true and really important in my mind,
but it seems that this is not what Tarjei really want.
The OP's problem is, well, whether the access specifier "overriding"
in derived class should be valid or not. Actually I do not think
Tarjei was confused by private virtual function overriding, at least
for his OP's context.
and also IMHO that faq is quite misleading.
Could you please elaborate on that, so that the FAQ could be improved?
That faq says:
[quote C++ FAQ Lite]
[23.4] When should someone use private virtuals? New!
Almost never.
|
That's not misleading; it's completely wrong. I think there's
pretty much a consensus among the experts that most virtual
functions should be private---some experts have even gone to the
point of saying that they should always be private.
| Quote: | Protected virtuals are okay, but private virtuals are usually a
net loss. Reason: private virtuals confuse new C++ programmers,
and confusion increases cost, delays schedule, and degrades risk.
New C++ programmers get confused by private virtuals because
they think a private virtual cannot be overridden. After
all, a derived class cannot access members that are private
in its base class
|
It's strange that I've never encountered this problem among new
C++ programmers. It's a question of education, but there's
really not the slightest ambiguity here. Private, in C++, does
not mean the same thing as private in Java, and if a beginning
programmer doesn't realize this, he's going to have problems
with overload resolution, amongst other things, and not just
overloading private virtual functions. (In fact, of course, as
soon as he sees a private virtual function, he will realize that
his understanding was wrong; if you couldn't override private
virtual functions, it would be illegal to declare a private
function virtual.)
| Quote: | so how, they ask, could it override a private virtual from
its base class? There are explanations for the above, but
that's academic. The real issue is that almost everyone
gets confused the first time they run into private virtuals,
and confusion is bad.
Unless there is a compelling reason to the contrary, avoid
private virtuals.
|
The compelling reason is programming by contract. And the fact
that it is a more or less standard idiom in C++.
| Quote: | [end quote C++ FAQ Lite]
This FAQ suggests we should keep from using private virtual
function, because this usage will confuse the C++ newcomers.
I see the point here, but I can not agree.
|
The idea of avoiding special features that a beginner might not
be familiar with is a good one, in itself. But you must bring
beginning C++ programmers up to speed with the standard idioms;
we don't create special iterators and avoid the STL simply
because beginners aren't familiar with using two iterators, and
are easily confused by it. And in this case, the issue concerns
a basic language element, which affects many, many aspects of
the code: private, in C++ does NOT mean what private means in
Java, and you must teach beginners what it really means, because
otherwise, they are going to be confused by many other things as
well, such as function overloading.
One can argue that the way C++ has defined certain things is
counter-intuitive. That may be (although in this particular
case, I think that the C++ solution is preferrable to the Java
one, even if it is less intuitive). But that's the way C++ is.
It's not part of the language that you can sweep under the table
and ignore. That's not true for everything, and I don't think
a beginner has to understand all of the subtilities of overload
resolution, for example, to be effective. But in this case, all
things considered, I think that the "counter-intuitive" meaning
of private in C++ is something that a beginner will not be able
to avoid.
| Quote: | Lets first limit the context to the language itself. It is now
well- known that class member should be private by default,
here member means both data member and function member. Since
virtual member belongs to function member, then the virtual
member should be private by default, unless in our derived
class the base version is required.
IIRC, Herb Sutter & Andrei Alexandrescu explained this issue
in their "C++ Coding Standards", also James Kanze (together
with other gurus) showed the same idea quite long time ago.
I agree with them on this point.
|
More than just citing a few experts who agree, I think it
interesting to note that until this FAQ entry, I'd never seen an
expert who disagreed. (Not everyone would go as far as Herb,
and say that virtual functions should never be public, but I
haven't seen anyone condemn the idiom per se.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Fri Sep 22, 2006 5:45 pm Post subject: Re: Private implementation of public pure virtual |
|
|
tarjei.knapstad (AT) gmail (DOT) com wrote:
| Quote: | Alf P. Steinbach wrote:
* Jiang:
{ See the FAQ item "When should someone use private
virtuals?" currently at <url:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.4>.
-mod }
Sorry but the above faq has litte to do with the OP's problem,
It concerns the very same issue. Access specifiers and
virtuality (the ability to override) are orthogonal
features: one does not affect the other, at the technical
level. The issue is then how these features can or should
be meaningfully mixed at the design level.
Firs off, thanks to everyone for clearing this up for me.
I was tempted to make the same comment about the FAQ entry not
being related to my question at first, but I see how they
relate now given the fact that virtuality/acess specs are
orthogonal.
I agree with others though - I still don't think that entry is
very useful. It starts with saying "Almost never", then goes
on to say "just avoid it to avoid confusion" and ends with
"unless there's a compelling reason to the contrary, avoid
private virtuals". What could this compelling reason be? It
basically just says "don't do it" without giving any rationale
beyond avoiding confusion.
|
Avoiding confusion is a very good reason. The problem is that
it doesn't apply in the way the FAQ presents it. As you have
correctly realized, access control (in C++) is orthognal to
other issues---it is also applied very late, after overload
resolution, etc. This is a very fundamental concept in C++;
IMHO, not understanding it leads to confusion in many different
places. And of course, once you've understood it, there is no
confusion with private virtual functions either.
(Personally---and I certainly don't speak for everyone here---I
find that orthognality reduces confusion. I find the fact that
access control isn't orthognal to other things in Java increases
confusion.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Herb Sutter Guest
|
Posted: Tue Sep 26, 2006 1:42 am Post subject: Re: Private implementation of public pure virtual |
|
|
"kanze" <kanze@gabi-soft.fr> wrote:
| Quote: | [quote C++ FAQ Lite]
[23.4] When should someone use private virtuals? New!
Almost never.
That's not misleading; it's completely wrong.
|
Eek, yes.
| Quote: | I think there's
pretty much a consensus among the experts that most virtual
functions should be private---some experts have even gone to the
point of saying that they should always be private.
|
I'm in the "private by default" camp, but there are some experts who
disagree. Public virtual is fine, especially for ABCs (interfaces), but in
other kinds of classes the programmer ought to understand that "public"
and "virtual" are two separate responsibilities, and why/what they are.
| Quote: | New C++ programmers get confused by private virtuals because
they think a private virtual cannot be overridden. After
all, a derived class cannot access members that are private
in its base class
It's strange that I've never encountered this problem among new
C++ programmers. It's a question of education, but there's
really not the slightest ambiguity here.
|
Actually, I encounter this almost every time explain "private virtual."
This does surprise new programmers. However, in my experience once you
explain it and point out that the accessibility label is only about who
may call the funtion, they immediately say "oh" and then never ask again.
Of course, Java and C# do it the other way, and lots of people find that
intuitive.
| Quote: | Unless there is a compelling reason to the contrary, avoid
private virtuals.
The compelling reason is programming by contract. And the fact
that it is a more or less standard idiom in C++.
|
Yes. Note that almost all virtual functions in the C++ standard library
are not public (IMO they should be private, but that's either a design
preference or a historical artifact).
| Quote: | (Not everyone would go as far as Herb,
and say that virtual functions should never be public,
|
Small correction: I never said "never." I variously wrote "prefer" or
"consider" making them private by default.
Herb
---
Herb Sutter (www.gotw.ca) (www.pluralsight.com/blogs/hsutter)
Convener, ISO WG21 (C++ standards committee) (www.gotw.ca/iso)
Architect, Developer Division, Microsoft (www.gotw.ca/microsoft)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|