From: Andrei Polushin on 15 Sep 2006 20:15 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 16 Sep 2006 07:58 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 16 Sep 2006 08:03 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 16 Sep 2006 13:53 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 16 Sep 2006 23:54 * 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! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: Callback-related libraries and terminology Next: fgets() vs std::getline() performance |