From: Jiang on
Richard Corden wrote:
> Jiang wrote:
> > Carlos Moreno wrote:
> >> 1) private is only used as class-member access specifier
> >>
> >
> > According to the holly standard, the memory layout
> > for variables separated by different access specifiers
> > is implementation issue. Therefore if you change
> > private to public, the member layout maybe different.
>
> My understanding is that the standard only talks about 'access
> specifiers' not 'different access specifiers'. So I believe that the
> layout of the following is unspecified:
>
> struct A
> {
> public:
> int i;
> public:
> int j;
> };
>

True.

> However, the point that they maybe different still holds, since it is
> unspecified, there is no guarantee that the above will have the same
> layout as:
>
> struct A
> {
> public:
> int i;
> private:
> int j;
> };
>
>

True.

"Separated by different access specifiers" is just a
specialized version of "separated by access specifiers".

Since this issue is totally unspecified by standard,
we can not make sure that replacing private with public
will give us the *exactly same* result/layout.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Jiang on
Carlos Moreno wrote:
> Jiang wrote:
>
> > For following example,
> >
> > struct B
> > {
> > int t;
> > };
> >
> > struct D1 : private B // private inheritance (hold-a)
> > {
> > D1(){ t = 0; }
> > };
> >
> > struct D2 : public D1
> > {
> > D2(){ t = 0; } // error, B::t is not accessible.
> > };
> >
> > So, again private and public make difference here.
>
> If I understand correctly, this example is not valid with respect
> to my question -- sure, private and public make a difference, but
> is not that what counts; I'm starting with a code *that compiles*;
> so, if I haev a privately inherited base class, then my code would
> only do what it is allowed to do. *Then* I replace the privately
> inherited to a publicly inherited. There shouldn't be any error
> now: I'm eliminating restrictions, so whatever I was able to do
> before, I'm able to do now, and more (except that, again, my
> question describes a situation where I will not do anything more,
> since I will *only* change the private keyword to public)
>

Well, my point is the private inheritance constructs a
"hold-a" relationship while public inheritance yields a
"is-a" relationship. If you replace private with public,
you create a inheritance chain, which is not available
in the original configuration.

Please check the nice examples purposed by Kanze
and Falk.

> > Actually I do not known any compilers really treat
> > private and public member differently, because
> > access specifiers are purely logical constructs.
>
> My thinking exactly. Private does not determine behaviour; it
> simply places semantic restrictions on what the program is
> allowed to do, not on the behaviour resulting from what the
> program does do.
>

Not true for case 2. My above comment was based on case 1.

And even for case 1, it is pretty valid that the compilers can
allocate private members in higher address, and put all public
members in other region, because here the allocation order
is unspecified behavior according to the standard.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Greg Herlihy on
Pete Becker wrote:
> Carlos Moreno wrote:
> >
> > If I now replace every single instance of the keyword private
> > with the keyword public (and I change *nothing else*), would
> > the behaviour of my program change? That is, in practical
> > terms, should I expect the behaviour of my program to change
> > when compiled with an *actual* compiler that is reasonably
> > compliant and reasonably high-quality?
> >
>
> Unlike Java, in C++ private members are considered in name lookup, so
> changing private to public doesn't affect lookup. It does, of course,
> affect accessiblity, but that means that some things that used to be ill
> formed because name lookup found something that wasn't accessible would
> become well formed. Since the program was well formed to begin with,
> that doesn't apply. The behavior of the program will be the same. (And
> any compiler that gets this wrong is so fundamentally broken that it's
> not on the market)

There is always the possibility that changing "private" to "public"
with a macro could turn a well-formed program into an ill-formed one:

class A
{
class B;

private:

class B {};
};

will compile with private as "private", but will not compile with
private as "public".

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carlos Moreno on
kanze wrote:

> "A translation unit that includes a header shall not contain any
> macros that define names declared or defined in that header.
> Nor shall such a translation unit define macros for names
> lexically identical to keywords." (I think that the first
> sentence is rather weak. It suggests that "#define allocator
> 42" would be legal before including <vector>, since allocator
> isn't defined in <vector>, but in <memory>. But obviously,
> <vector> is going to include <memory>.)

Nit pick: I believe your reasoning is incorrect -- well, at
least one can object. It comes down to what we call "defined
in that header" -- If <vector> includs <memory>, then allocator
is defined in the header <vector> -- The header <vector> has
several ways of #defining a symbol; one of them is to use a
#define directive; another one is to #include a header where
the symbol is defined (notice the recursive nature of my
"definition".

Anyway, perhaps a better phrasing would have been: "names that
the header declares or defines" -- this is, IMO, unambiguous,
since it doesn't say anything that suggest a given mechanism
to declare or define.

Anyway, coming back to the original point: since my question
is rather practical in nature, and not "language lawyering",
I'm now curious as to whether I should expect any concrete
manifestation (read: nasty effect) of that undefined behaviour
that occurs when I #define private having included standard
headers...

>>An object containing different access types may be laid out in
>>an implementation-defined manner. Changing the access
>>specifiers may cause the implementation to change the ordering
>>of the members. [...]
>
> This could also cause a change in behavior. [...]

> A anA ;
> if ( &anA.a > &anA.b ) //...
>
> In this case, of course, the code has unspecified behavior to
> begin with [...]

> I don't think that this was what Carlos had in mind

Indeed. I mentioned that I start off with a strictly legal
C++ program -- I'm not sure if that implies, strictly speaking,
unspecified or implementation-dependent behaviour, but in my
mind, I was assuming that the program that I start with is
clean enough that it doesn't have any sort of nasties like
the above.

Still, you make a very good and very interesting point, if
only for the fun of thinking about it, and not for the
practical implication it may have with respect to my
original question.

>>My vote is: behavior no; binary image maybe.
>
> The actual examples outvote you, two to one:-).

:-)

It still looks like for the use that I have in mind, which
implies the assumption that I'm starting with a program that
is clean enough and that it does not have bahaviour that is
unspecified, implementation dependent, or undefined, my
initial guess seems correct (assuming that the undefined
effect resulting from #defining a keyword having #included
standard headers does not materialize in practice, with
actual compilers and actual standard library implementations).

Thanks,

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carlos Moreno on
Jiang wrote:

> Actually I do not known any compilers really treat
> private and public member differently, because
> access specifiers are purely logical constructs.
>
> But I do not have a good reason to do such a
> replacement. :-)

No one has explicitly asked me to say why I was asking
such a strange question.

But having seen a few interesting replies, it could be
a good thing to mention that detail.

What I have in mind is debugging/testing (QA kind of
testing). Having client code (the "test protocol")
access to private data members gives you more flexibilty
in terms of easily creating test case scenarios. Of
course, if we're talking production code, I wouldn't
want to even open the source file with a text editor
after the test protocols passed!

In particular, changing all the private to public
is about the worst possible idea!! First of all,
one could *accidentally* change something else that
goes unnoticed. One could then, after all the test
protocols passed and we want to restore the original
file, *forget/overlook* to change back one or several
of the publics, leading to future bugs or trouble.
Also, though less severe consequences, we could
accidentally change a public back to private when
that one was originally a public, leading to
unnecessary annoyment.

That's why I thought #defining private as public for
the purpose of compiling the prorgam that runs the
test protocols would be the least intrusive and
safest way to do that trick. #Defining it from the
command-line with a compiler switch is the safest
way.

One concern, however, is due to the fact that the
generated binaries could change -- that forces us
to remember to recompile the non-testing version
right after we're finished; otherwise, if we leave
the object file and there are no more changes to
the corresponding source file, the next time that
we link it (because other modules changed), we might
run into trouble, since some of the object files are
compiled with one class declaration, and the object
file that we tested in the past with a different
declaration, leading to inconsistent binaries (that
is, there is the possibility).

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]