C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

overload resolution before access checking

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Walter Bright
Guest





PostPosted: Sun Jul 09, 2006 4:25 am    Post subject: overload resolution before access checking Reply with 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?

[ 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





PostPosted: Sun Jul 09, 2006 7:26 pm    Post subject: Re: overload resolution before access checking Reply with quote



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





PostPosted: Mon Jul 10, 2006 2:00 am    Post subject: Re: overload resolution before access checking Reply with quote



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





PostPosted: Mon Jul 10, 2006 2:11 am    Post subject: Re: overload resolution before access checking Reply with quote

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





PostPosted: Mon Jul 10, 2006 2:12 am    Post subject: Re: overload resolution before access checking Reply with quote

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





PostPosted: Mon Jul 10, 2006 3:12 am    Post subject: Re: overload resolution before access checking Reply with quote

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





PostPosted: Tue Jul 11, 2006 2:28 am    Post subject: Re: overload resolution before access checking Reply with quote

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





PostPosted: Tue Jul 11, 2006 2:38 am    Post subject: Re: overload resolution before access checking Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.