From: Andrei Polushin on
Carlos Moreno wrote:
> 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. :-)
>
> [...]
>
> 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.

You may encounter problems at least with Visual C++ (other compilers
may behave this way): it uses different name linkage for private
functions. In particular, the following program will not link:

----------------------------------------------- A.h
class A {
private:
void f();
};
----------------------------------------------- A.cpp
#include "A.h"

void A::f() { } // linker symbol "private: void A::f()"
----------------------------------------------- main.cpp
#define private public
#include "A.h"

int main()
{
A a;
a.f(); // linker: unresolved "public: void A::f()"
}
-----------------------------------------------


> In particular, changing all the private to public
> is about the worst possible idea!!

I agree, you are to use public interfaces in your tests.

The recommendation is a more granular design: every unit is rather
small and has testable public interface, even if some units are
private for casual user. E.g. we can use forward declarations to make
some classes privately declared. Or we can use "pimpl" idiom to hide
private dependencies with their declarations.

--
Andrei Polushin


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

From: Carlos Moreno on
Andrei Polushin wrote:

>>[...]
>>
>>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.
>
>
> You may encounter problems at least with Visual C++ (other compilers
> may behave this way): it uses different name linkage for private
> functions. In particular, the following program will not link:
> [...]

That's not really a terrible problem -- I can recompile all the
modules I need to recompile; if we're talking about a very large
project, then that would be a problem; but the debugging test
case scenario should be relatively simple, and should not involve
recompiling half the known universe.

>>In particular, changing all the private to public
>>is about the worst possible idea!!
>
> I agree, you are to use public interfaces in your tests.

Oh wait -- I think you misunderstood; what I meant is that
opening the file with a text editor and *modifying* the file
(replacing private with public) is the worst possible idea.

> The recommendation is a more granular design: every unit is rather
> small and has testable public interface [...]

This is also important (and the test protocol *must* exhaustively
test the functionality of the public interface), but does not
necessarily preclude the usefulness of the test protocol *also*
having access to the private interface.

In particular, imagine a case where you want to validate certain
consistency constraints in the data (say, you have two integer
data members, d_start and d_end, and it must always hold true
that d_end >= d_start). You could have a function that validates
such consistency constraints; how do you verify that function?

It would be great to have access to the private data members to
be able to manufacture inconsistent data and veify if the
function detects the inconsistency -- it could be otherwise
hard; I mean, sure, you could extract and isolate that
function and test it, but then that fails to test it when
interacting with the rest (my example of two ints is quite
silly, but the principle is valid in the general case, when
the consistency constraints to be evaluated is more complex).

Also, what happens if you need to check something that happens
at a very high level? What I mean is that the design may be
granular, but you need to verify something that involves
20 levels of "sub-objects" and delegation, involving perhaps
a long sequence of past events that have led to the present
state. It could be easier to simply "manufacture" (by having
access to private data members) what we know would be the
accumulated effect of those past events, and then test it,
instead of having to reproduce the long list of past events;
maybe you don't even know what that list of past events is,
and maybe you're trying to verify what your code does when,
as the result of who knows what past events, you reach a
certain present state.

I'm not saying that #defining private as public is the way
to run test protocols; I simply think that it is an
interesting alternative, that can be quite useful in certain
situations -- I wanted to know if I should expect the trick
to work in the general case.

Cheers,

Carlos
--

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

From: James Kanze on
Carlos Moreno wrote:
> kanze wrote:

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

The above is strictly legal. The standard just doesn't make any
guarantees with regards to whether the condition in the if is
true or not. So it is a strictly legal program with two
different possible outputs. (And it's unspecified which will
occur.)

Strictly legal, of course, doesn't mean that it has any
practical utility:-). I can't imagine anything along these
lines in real code.

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

I'm not sure I agree. In particular, I can imagine that the
example with the exception crops up occasionally in real code
(and I wouldn't say that the example with dynamic cast is
unreasonable either, although I can't think of a good case where
it would be used off hand).

--
James Kanze (Gabi Software) email: kanze.james(a)neuf.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! ]

From: Carlos Moreno on
James Kanze wrote:

>>>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 [...]
>
> The above is strictly legal. [...]
>
> Strictly legal, of course, doesn't mean that it has any
> practical utility:-). I can't imagine anything along these
> lines in real code.

That's exactly what I meant -- since the application I had in
mind for the private/public trick involves production code, we
work with the assumption that the code is *clean* enough to be
free of undefined, unspecified, or implementation-dependent
code (well, maybe a few "clean" platform-dependent things
here and there -- for a suitable definition of "clean" :-)).

That the assumption holds or not, that's another thing, but
we have to work under that assumption -- in fact, if changing
private to public changed the behaviour of the program, then
I would call it a *big success* as far as test protocols go!!
We detected an unspecified-behaviour condition that most
likely should not be there (if we're talking production code).
Kind of the same idea as memory/environment disruptors.

>>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).
>
>
> I'm not sure I agree. In particular, I can imagine that the
> example with the exception crops up occasionally in real code
> (and I wouldn't say that the example with dynamic cast is
> unreasonable either, although I can't think of a good case where
> it would be used off hand).

As I said, I was mostly interested in the case of private
being used for member access specification, given that
private inheritance is supposed to be rare (it is rare in
my code anyway -- I would venture to say that it does not
show up *ever* in my "high level" real code, which is the
one I would be debugging with this trick; the lower-level
"foundational" code is supposed to be completely general-
purpose and stand-alone that it can be tested easily with
regular methods).

Plus, the only case where it seems to matter is when catch
clauses for both the base and the privately inherited class
are used *in that particular order* -- seems kind of specific
to be quite rare in real code. For overloading resolution
(including templates combined with overloaded functions), I
can't come up with an example in which things would change --
if you have overloaded functions receiving B and D, then
regardless of the relationship D is-a B holding or not, if
you pass a B or a D, you have exact match; if you have a
function receiving B and a template for the rest, then when
you call it with a D, regardless of the is-a relationship,
the template version will always be chosen, since an implicit
conversion is needed, whereas the instantiated template
provides an exact match. Am I missing something?

Carlos
--

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

From: Alf P. Steinbach on
* Carlos Moreno:
>
> I'm not saying that #defining private as public is the way
> to run test protocols; I simply think that it is an
> interesting alternative, that can be quite useful in certain
> situations -- I wanted to know if I should expect the trick
> to work in the general case.

From a practical point of view I think so.

From a formal point of view you're prohibited from defining a macro
with the same name as a keyword if any standard library headers are
included.

An alternative is to directly support testing in the classes (it can be
as simple as a "friend" declaration).

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