 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Walter Bright Guest
|
Posted: Sun Jul 09, 2006 4:25 am Post subject: overload resolution before access checking |
|
|
Given:
-----------------
struct S
{
public:
void foo(long);
private:
void foo(int);
};
.....
S s;
s.foo(1); // error, S::foo(int) is private
------------------
In other words, overload resolution happens before access checking. If
it happened after access checking, then S::foo(long) would have been
selected.
What is the rationale for this behavior (which has been in C++ since at
least 1986)? Shouldn't private members be invisible rather than
inaccessible?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
James Dennett Guest
|
Posted: Sun Jul 09, 2006 7:26 pm Post subject: Re: overload resolution before access checking |
|
|
Walter Bright wrote:
| Quote: | Given:
-----------------
struct S
{
public:
void foo(long);
private:
void foo(int);
};
....
S s;
s.foo(1); // error, S::foo(int) is private
------------------
In other words, overload resolution happens before access checking. If
it happened after access checking, then S::foo(long) would have been
selected.
|
Unless this code was in a member function of S, in which case
S::foo(int) would have been selected and called.
| Quote: | What is the rationale for this behavior (which has been in C++ since at
least 1986)? Shouldn't private members be invisible rather than
inaccessible?
|
There seem to be rough guidelines that providing additional
access should not change the meaning of code, including not
making valid code invalid. In simple cases that's still
true. If prefers a diagnostic to a subtle, silent change;
there's little chance that code as you showed above is
deliberate, and code using that class would behave
differently depending on where it was if the private
members were invisible from outside of the class.
It can be useful to have private members being visible but
inaccessible, for example to "poison" certain operations
so that they can't be inadvertently used.
Diverting slightly: what would it even mean to have an
invisible private copy constructor? The compiler wouldn't
synthesize one, as one has been declared, but code outside
the class can't call it if it's invisible... so would we
have a brand new case where no copy constructor was found
at all?
I think C++'s rules that access checking is done late are
somewhat counter-intuitive, but providing some robustness
and are straightforward once understood. In other languages
(say Java), there are unpleasant interactions between
overloading, overriding and access control (for example,
a class can't privately implement an interface, which
rules out one useful technique for giving different
clients of the class access to only the interface they
need).
-- James
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Mon Jul 10, 2006 2:00 am Post subject: Re: overload resolution before access checking |
|
|
Walter Bright wrote:
| Quote: | struct S
{
public:
void foo(long);
private:
void foo(int);
};
....
S s;
s.foo(1); // error, S::foo(int) is private
[...]
What is the rationale for this behavior (which has been in C++ since at
least 1986)? Shouldn't private members be invisible rather than
inaccessible?
|
The design goal was that, as long as the code remains well-formed,
changing a member's access level shall not change the semantics
of the program.
Falk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Walter Bright Guest
|
Posted: Mon Jul 10, 2006 2:11 am Post subject: Re: overload resolution before access checking |
|
|
James Dennett wrote:
| Quote: | Unless this code was in a member function of S, in which case
S::foo(int) would have been selected and called.
|
Right, there would be different behaviors depending on the context in
which foo() is invoked.
| Quote: | What is the rationale for this behavior (which has been in C++ since at
least 1986)? Shouldn't private members be invisible rather than
inaccessible?
There seem to be rough guidelines that providing additional
access should not change the meaning of code, including not
making valid code invalid. In simple cases that's still
true. If prefers a diagnostic to a subtle, silent change;
there's little chance that code as you showed above is
deliberate, and code using that class would behave
differently depending on where it was if the private
members were invisible from outside of the class.
|
That is as I suspected, but I am wondering if I am missing something
more significant.
| Quote: | It can be useful to have private members being visible but
inaccessible, for example to "poison" certain operations
so that they can't be inadvertently used.
|
Ok. It would prevent, for example, the compiler passing over it and
using a base class operation instead.
| Quote: | Diverting slightly: what would it even mean to have an
invisible private copy constructor? The compiler wouldn't
synthesize one, as one has been declared, but code outside
the class can't call it if it's invisible... so would we
have a brand new case where no copy constructor was found
at all?
|
It is hard to see what the ripple effect of this might be.
| Quote: | I think C++'s rules that access checking is done late are
somewhat counter-intuitive, but providing some robustness
and are straightforward once understood. In other languages
(say Java), there are unpleasant interactions between
overloading, overriding and access control (for example,
a class can't privately implement an interface, which
rules out one useful technique for giving different
clients of the class access to only the interface they
need).
|
Are private members invisible in Java? I agree that the subtlety
interactions between all these features can be difficult to predict in
advance.
-Walter Bright
www.digitalmars.com C, C++, D programming language compilers
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Walter Bright Guest
|
Posted: Mon Jul 10, 2006 2:12 am Post subject: Re: overload resolution before access checking |
|
|
Jack Klein wrote:
| Quote: | What is the rationale for this behavior (which has been in C++ since at
least 1986)? Shouldn't private members be invisible rather than
inaccessible?
The rationales for choices made in the standard are better discussed
in comp.std.c.
|
I thought it would be better here, as the choice predates the standard
by over a decade, and there's no possible way it could be changed.
| Quote: | At a reasonably educated guess, however, I would say
because it would greatly complicate compilers to do things the way you
want, and would produce less useful error messages as well.
|
I am not suggesting that I want this to change. I am simply trying to
understand the rationale behind it.
I agree it would be harder to implement, but implementation difficulty
doesn't seem to have ever been a factor - C++ is the hardest language to
implement, by far <g>. Poor error messages have also plagued C++ because
of lack of redundancy in the syntax, but I'm not convinced that the
different access mechanism would make things better or worse.
-Walter Bright
www.digitalmars.com C, C++, D programming language compilers
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Mon Jul 10, 2006 3:12 am Post subject: Re: overload resolution before access checking |
|
|
Walter Bright <walter@digitalmars-nospamm.com> writes:
| Quote: | Given:
-----------------
struct S
{
public:
void foo(long);
private:
void foo(int);
};
....
S s;
s.foo(1); // error, S::foo(int) is private
------------------
In other words, overload resolution happens before access checking. If
it happened after access checking, then S::foo(long) would have been
selected.
What is the rationale for this behavior (which has been in C++ since at
least 1986)? Shouldn't private members be invisible rather than
inaccessible?
|
I'm pretty sure I read the answer to this (like most other C++
rationale questions) in D&E.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Tue Jul 11, 2006 2:28 am Post subject: Re: overload resolution before access checking |
|
|
Walter Bright wrote:
[...]
| Quote: | Are private members invisible in Java?
|
Yes. In addition, they are implicitly final.
| Quote: | I agree that the subtlety interactions between all these
features can be difficult to predict in advance.
|
I don't think that there's a perfect solution. I find the C++
solution rather robust, and don't have problems with it, but
that doesn't mean that other solutions are necessarily wrong.
--
James Kanze kanze.james (AT) neuf (DOT) fr
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 |
|
 |
Dave Harris Guest
|
Posted: Tue Jul 11, 2006 2:38 am Post subject: Re: overload resolution before access checking |
|
|
walter@digitalmars-nospamm.com (Walter Bright) wrote (abridged):
| Quote: | In other words, overload resolution happens before access checking. If
it happened after access checking, then S::foo(long) would have been
selected.
What is the rationale for this behavior
|
There is none.
In Stroustrup's D&E book he says he can't remember, but he thinks it just
fell out of the way the first parser was written without being consciously
chosen. It does mean that access control does not affect the semantics of
a program, only whether it compiles, but that wasn't the motivation for
it.
| Quote: | Shouldn't private members be invisible rather than inaccessible?
|
In any case, they are visible to the virtual dispatch mechanism.
#include "base.h"
class Derived : public Base {
private:
void dontCallMe() const;
};
Here Derived::dontCallMe() can in fact be called if the base class is
like:
class Base {
public:
virtual void dontCallMe() const;
}
The private Derived function overrides the public, virtual Base one even
though it is not itself declared virtual. This is one of the reasons
inheritance remains a dangerous, tightly-coupled relationship in C++.
-- Dave Harris, Nottingham, UK.
[ 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
|
|