Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!cs.utexas.edu!pp!riunite!rfg From: rfg@riunite.ACA.MCC.COM (Ron Guilmette) Newsgroups: comp.lang.c++ Subject: Re: More nits to pick at... Message-ID: <193@riunite.ACA.MCC.COM> Date: 2 May 89 19:45:21 GMT References: <190@riunite.ACA.MCC.COM> <9279@alice.UUCP> Reply-To: rfg@riunite.UUCP (Ron Guilmette) Organization: MCC Austin, Texas Lines: 307 I would like to extend my warm thanks to Andrew Koenig for taking the time to formulate concise (and precise) answers to my second set of nit picking questions. I hope that other readers of this newsgroup will benefit from the public availablity of this information at least as much as I have. I also hope that Bjarne may be able to make some use of my tendency to nit-pick. Specifically, I hope that some of the questions and answers exchanged here will help to make the forthcomming new reference manual a more robust source of information for other nit-pickers like me. Although Andrew's answers were all quite clear and to the point, there are one or two minor nits I feel compelled to re-pick. The re-pickings follow below: In article <9279@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes: >Here's my try at answering Ron's questions. My comments are indented: >------------------------------------------------------------------------ > > Summer. We're still on target for June 30. Why not just round it off and call it Independence Day? That's pretty close but gives you about an extra week? :-) >How can you declare a function which can accept a pointer >to itself as an argument (in a type-safe manner of course)? > > You can't in C++ or C. Well, so is anybody (other than me) concerned about this? >Is it legal to declare an operator which takes no >struct/class parameters but which does take at least >one union parameter? At least one enum parameter? > > A union is a class, so yes. An enumeration isn't a class, so no. OK. So is there any reason (good or otherwise) for the rule that says that that each user-defined operator must accept at least one struct/class/union parameter? Is there any reason why this rule could not be relaxed so as to say that each operator must accept at least one struct/class/union/enum? >If a constructor makes calls to virtual member functions >which are declared (and defined) for the constructor's >own class, do these calls ever go through the virtual >function table? If so why? > > Suppose that class D is derived from B. > Then constructing a D involves constructing a B first. > > Objects are constructed in exactly the same way > regardless of whether they are part of other objects. > Thus while the B is being constructed, it has no > knowledge of whether or not it's part of a D. Is this an exception to a more general rule? What I mean is this: Is it also true to say that "Objects are *operated on* in exactly the same way regardless of whether they are part of other objects." Please correct me if I am wrong (I often am when it comes to C++) but if a base class contains two virtual member functions, and if the second one contains a call to the first one, and if the second one is invoked for an object of a derived class which has the first virtual function overloaded, which version of the first (virtual) function gets called? An example: struct base { virtual first () {} virtual second () { second (); } }; struct derived : public base { virtual first () {} }; void test () { derived d; d.second (); } In this case, which version of first() will get called? (I think I know the answer, but I just want to be sure that things *do* work differently within constructors, i.e. that "virtual-ness" doesn't count as much as it does normally. > It follows from this that if B's constructor calls > one of B's virtual functions, directly or indirectly, > the behavior is as if the B were being constructed > in isolation. You get the function from B or > one of its base classes, but never the function > from D or any other derived class of B. So the call (within the constructor) to "one of B's virtual functions" obviously *does not* go through the vtable. Fine. To that extent, you are obviously correct in saying that things behave "as if B were being constructed in isolation". What happen however if we are constructing a "D_object" and we thus (as a consequence) end up executing B's constructor, and then B's constructor invokes one of B's virtual methods, and ***then*** the given virtual method of B itself invokes another one of B's virtual methods (which happens to also be overloaded in D)? *** This is *not* an idle question. You said that things behave "as if B were being constructed in isolation" (i.e. without an knowledge of the fact that the B being constructed is a part of a D). Is that true ALL THE WAY, or only as long as you are doing operations from directly within B's constructor? >Is there any way to specify (explicitly) the order in which >members and base classes are destructed? > > They are destroyed in inverse order from construction. > There is no way to control the order of destruction > except by ordering your declarations to control the > order of construction. Why would you want to? Sorry. This was a dumb question, but I feel a bit vindicated because I have just noticed that your answer is somewhat incorrect. On pages 8-10 of the 1987 Workshop Proceedings the ability to specify various constructors which can themselves specify various construction orderings is described. However, on page 10 (paragraph #2) when discussing order of destruction, its says: "There is no way for the programmer to control this order". This seems very asymmetric to me. Is there any (good) reason for this asymmetry? >Is it legal to declare a function as inline and later give >either another declaration or a definition for the function >whose heading does *not* include the keyword "inline"? > > Yes. OK. New question. If you can do this, then following the later "non-inline" declaration/definition should the compiler still consider the function to be a candidate for inlining? >Is it legal to declare a function as non-inline and later >to redeclare it (or give a definition for it) which is inline? > > Yes, but if you want to declare a function inline, > you must do so before the first place you use it. Otherwise what? Are you saying that the following code contains an error? If so what line is it on? void function (); void test () { function (); } inline void function () { } >Are enum type values always treated like int type values >or can they be used to disambiguate a function call, i.e.: > > Enumerated types are separate types, so they can > be used to disambiguate a function call... OK. So enum type are *not* treated like int's! Ah, ha! Which of the following things are legal, which are illegal? enum color { red, orange, yellow }; int array[color]; // legal ? color c, c2; int i; char* cp; ... i = c; c = i; c = -c; // unary negation ? c = c + c; c = c - c; c = c * c; c = c | c; // bitwise operators ? i = c == c2; // simple comparisons ? i = c > c2; // ordered comparisons ? i = c == i; cp = &cp[c]; // index cp = cp+c; // pointer arithmetic >At the end of section 8.9 in the reference manual there is a short >note about how to get the address of a particular instance of an >overloaded function... > Sorry. The only places you can do overloaded selection is > in assignment and initialization... Don't be sorry. I'm sorry for you! :-) GNU C++ allows disambiguation of a function reference via casting, i.e.: void* p = (function_of_one_int) &my_overloaded_function; This appears to be a reasonable thing to allow, and I'm glad that GNU C++ allows it (even if cfront 2.0 may not). >May an expression supplied as a default function argument contain a reference to: > > d) the address of the function for which the formal parameter > list is being specified? > > If this means what I think it does, the answer is no -- > how would you write the type of the argument? This relates to an earlier question I had asked. You can't do it in a strictly type-safe way. But how about this: class C; typedef void (C::*Cmp) (int, ...); class C { public: void member (int i = 99, Cmp ptr = &member) {} }; This brings up another question which I forgot to ask. Is it legal to use a call to a member function as part of the default value expression for a parameter of another function within the same class, i.e.: class C { public: int member_1 () { return 99; } void member_2 (int i = member_1 ()) {} }; >Is it legal or illegal to put an "overload" statement inside a function? >Inside a class? A struct? A union? Is it ever of any value to nest >overload statements within these contexts? > > The `overload' declaration is obsolescent in 2.0 -- > all functions are (potentially) overloaded. This *is* surprizing. Tell me something. I got the impression that one reason (in cfront 1.2, g++, etc.) that you would *avoid* using an "overload" declaration for a given global function was that you could then be sure that the name of that function would *not* be mangled on its way to assembly (or C) code. This was/is useful in cases where you want to link your C++ programs to code written in some other language. Are you saying that in 2.0, *all* the names of all global functions will be mangled and that there will be no way to prevent this? >Is it ever legal to specify a return type for either a constructor or >a destructor? Specifically, is it legal for constructors and/or >destructors to return (a) void, or (b) void*, or (c) class_type*, >where "class_type" is the name of the containing class? > > No. G++ allows you to explicitly declare the return type of constructors as type "pointer-to-class" where "class" is the class being constructed. Similarly, it allows you to explicitly declare the type of any destructor to be "void". Are you saing that G++ is wrong in both cases? >Is it legal or illegal to place a declaration for a member function >within one "visibility section" (i.e. "public", "private", or "protected") >of a class declaration and then to subsequently re-declare the same >member function (with the same parameter list) in a different "visibility >section" of the same class declaration, for example: > > class base { > protected: > void member (int i); > public: > void member (int i); // legal ? > private: > void member (int i) {} // legal ?? > }; > > No. A member may be declared no more than once in a > class declaration... I don't believe that that is true. Can you quote a page number for me on this? Perhaps Bjarne will leap in at this point. Actually, it has been my understanding that the following is legal: class C { public: void member_1 (int i, int j); void member_2 () { member_1 (88, 99); } void member_1 (int i, int j = 88); void member_3 () { member_1 (77); } void member_1 (int i = 22, int j = 33) { } }; The Book says that you can re-declare a function and add additional default parameter values. Now if this *is* legal, then my original question (regarding re-declaration of member functions in different visibility sections of a class declaration) still needs to be given a proper answer. -- // Ron Guilmette - MCC - Experimental Systems Kit Project // 3500 West Balcones Center Drive, Austin, TX 78759 - (512)338-3740 // ARPA: rfg@mcc.com // UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg