From: Jiang on
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.


> 2) private is also used for inheritance.
>

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.
Someone could use above behavior to implement
compile-time checking/assertion, maybe.

> (I believe the answer NO is valid for both cases, but I'm
> mostly interested in case (1), so if the answer is different,
> please specify the reasoning for both cases).
>


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. :-)


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

From: kanze on
Jack Klein wrote:
> On 14 Sep 2006 19:57:17 -0400, Carlos Moreno
> <moreno_at_mochima_dot_com(a)mailinator.com> wrote in
> comp.lang.c++.moderated:

> > Say that I have a C++ program that consists only of
> > perfectly valid C++ code (in other words, the program
> > compiles and does not invoke undefined behaviour).

> > 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?

> I would not expect the behavior to change.

class B
{
} ;

class D : private B
{
} ;

int
main()
{
try {
throw D() ;
} catch ( B const& ) {
return 0 ;
} catch ( D const& ) {
return 1 ;
}
return 2 ;
}

Or:

struct B
{
virtual ~B() {}
} ;

struct D : private B
{
B* myB() { return this ; }
} ;

int
main()
{
B* p1 = (new D)->myB() ;
D* p2 = dynamic_cast< D* >( p1 ) ;
return p2 == 0 ;
}

Compiling with -Dprivate=public results in a different return
value in each case. (It also results in a warning that the
second catch clause cannot be activated in the first example.)

> > As a corollary: if I simply add, at the beginning of the
> > file, the following line:

> > #define private public

> I am pretty sure that using a macro to redefine a keyword is
> undefined in C++, but I will admit that I couldn't find that
> in a quick look at the standard.

It's not, as long as you don't include a standard header.
(That's why my two examples above depend on a difference in the
return code, rather than outputting something.) ?17.4.3.1.1/2:
"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>.)

Why should defining a macro to change a keyword be a problem
otherwise?

> But let's assume it does not, or your implementation
> ignores it.

> > And change *nothing else*, would I expect the behaviour of
> > the program to change?

> The behavior of the program should not change for any reason
> that I can think of.

See above. It does. (At least with g++, but I'm pretty sure
that it is conformant here.)

[...]
> 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 would likely cause the machine code to
> change, as some instructions might well include the offset in
> an address or as an index to a pointer.

This could also cause a change in behavior. Imagine a compiler
which always places private members first, and otherwise
respected the order of declaration. Then, given:

struct A
{
int a;
private:
int b;
}

A anA ;
if ( &anA.a > &anA.b ) //...

In this case, of course, the code has unspecified behavior to
begin with, and so the change falls within a much larger set of
possible changes. In theory, at least, a compiler could change
the order of evaluation in an expression according to whether
elements were private or public; if the observable behavior of
the program depended on such ordering, it would change.

I don't think that this was what Carlos had in mind, but it is
certainly clear that in any program which has several possible
legal behaviors, changing private to public could potentially
change the behavior.

In practice, I don't know of a compiler where this would be the
case (but the behavior may change for other reasons, e.g.
different optimization options).

> > The answer that my mind gives me is: not sure about the
> > machine code; but for the behaviour of the prorgam: no, it
> > does not change -- I can't think of any reason why it could
> > change; but never say never, and I'm sure with the armada
> > of experts and gurus out there, if there is any such reason,
> > I will find out :-)

> > If necessary, please divide the answer into the following
> > two cases:

> > 1) private is only used as class-member access specifier

I think that it was once an expressed goal that changing private
to public here would make no difference in the specified
observable behavior of a program. As pointed out above, it's
rather obvious that it is allowed to make a difference when more
than one behavior is acceptable, i.e. the order of evaluation in
an expression---such differences may occur even without any
change to the code; differences due to data layout are
explicitly possible as well, beyond the ones normally possible,
but these, too, are due to differences allowed in the data
layout only in the case where some of the data is private.

> > 2) private is also used for inheritance.

There are definite, explicit and required differences here, as
shown above.

> > (I believe the answer NO is valid for both cases, but I'm
> > mostly interested in case (1), so if the answer is
> > different, please specify the reasoning for both cases).

> My vote is: behavior no; binary image maybe.

The actual examples outvote you, two to one:-).

--
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! ]

From: Richard Corden on
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;
};

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;
};


Regards,

Richard


--
Richard Corden

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

From: Martin Bonner on

Jack Klein wrote:
> On 14 Sep 2006 19:57:17 -0400, Carlos Moreno
> <moreno_at_mochima_dot_com(a)mailinator.com> wrote in
> comp.lang.c++.moderated:
>
> >
> > Say that I have a C++ program that consists only of perfectly
> > valid C++ code (in other words, the program compiles and does
> > not invoke undefined behaviour).
> >
> > 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?
>
> I would not expect the behavior to change.
>
> > As a corollary: if I simply add, at the beginning of the
> > file, the following line:
> >
> > #define private public
>
> I am pretty sure that using a macro to redefine a keyword is undefined
> in C++, but I will admit that I couldn't find that in a quick look at
> the standard. But let's assume it does not, or your implementation
> ignores it.
>
> > And change *nothing else*, would I expect the behaviour of
> > the program to change?
>
> The behavior of the program should not change for any reason that I
> can think of.
>
> > As a corollary of the corollary, how about using the compiler
> > switch -Dprivate="public" to introduce the #defined symbol
> > without touching the source code? (I guess this is exactly
> > the same as the previous case, right?)
>
> Ignoring (possible) undefined behavior, and assuming that the compiler
> option does what most compilers do with it, since the language does
> not define this method of defining a macro, I still agree I would not
> expect a change in behavior.
>
> > In all of the above: should I expect the generated machine
> > code to change? (assuming all the compiler switches and
> > optimization settings are exactly the same)
>
> Here there's a much better chance of seeing a change, especially if
> the class initially had public and private members before you changed
> them all to public.
>
> 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
> would likely cause the machine code to change, as some instructions
> might well include the offset in an address or as an index to a
> pointer.
>
> > The answer that my mind gives me is: not sure about the
> > machine code; but for the behaviour of the prorgam: no,
> > it does not change -- I can't think of any reason why it
> > could change; but never say never, and I'm sure with the
> > armada of experts and gurus out there, if there is any
> > such reason, I will find out :-)
> >
> > If necessary, please divide the answer into the following
> > two cases:
> >
> > 1) private is only used as class-member access specifier
> >
> > 2) private is also used for inheritance.
> >
> > (I believe the answer NO is valid for both cases, but I'm
> > mostly interested in case (1), so if the answer is different,
> > please specify the reasoning for both cases).
> >
> > Thanks for any comments,
> >
> > Carlos
>
> My vote is: behavior no; binary image maybe.

Actually, I think it might change if the behaviour depends on
implementation defined behaviour. Consider
struct Example {
public: char a;
private: int b;
private: char c;
.....
};

If you have some code which bahaves differently if the address of b is
less or greater than the address of a, then you are into implementation
dependant behaviour (which is OK). The implementation (and hence the
program) MIGHT behave differently if private turns into public.


[ 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:

> 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)

> 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.

Carlos
--

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