Xref: utzoo comp.lang.c++:13511 comp.std.c++:922 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!dali.cs.montana.edu!uakari.primate.wisc.edu!sdd.hp.com!cs.utexas.edu!ut-emx!jamshid From: jamshid@ut-emx.uucp (Jamshid Afshar) Newsgroups: comp.lang.c++,comp.std.c++ Subject: Re: Constructor Limitation: [Was: Re: Constructor question] Summary: make another constructor Keywords: constructor warnings Message-ID: <49133@ut-emx.uucp> Date: 17 May 91 07:25:55 GMT References: <1991Apr18.005426.21863@dragon.wpd.sgi.com> <71952@microsoft.UUCP> Followup-To: comp.lang.c++ Organization: The University of Texas at Austin; Austin, Texas Lines: 94 In article dsouza@gwen.cad.mcc.com (Desmond Dsouza) writes: >All data members which are objects have to be initialized before >the body of the constructor. There is this basic problem with >computing arguments for constructors in the initialization list: > > You cannot compute any temporaries (e.g. common subexpressions) > which are needed for initialization of such data members. struct A { A(int m, int n); }; struct B { A a1; B(int j) : a1( F1(j), F1(j)+1 ) {} // F1(j) is very time-cosuming }; >// Here is what I would like to do, in a completely fictitous >// and probably highly ambiguous syntax: > >B::B(int j) >: > { int f1 = F1(j); > a1(f1, f1+1); > } >{ > .. actual constructor body >} > >Using globals, "memoizing" functions, etc. is not a solution to this. > >Desmond D'Souza, MCC CAD Program | ARPA: dsouza@mcc.com When I need to do general compuation during class member initialization I use static member functions, but they can't help in your example. I encountered a similar problem in which I had a Base class constructor which took two parameters and a Derived class always passed it duplicate items (ie. Base(foo(j), foo(j))) where foo(j) was time-consuming. What I did was add another constructor to Base which only took one parameter. This was a good move as it turned out I needed to do this kind of construction just as often as the original way. Another solution if you do not want to mess with the Base class is to create an intermediate class. One solution to your example is to define class A above to be: struct A { A(int m, int n); A(int m); // construct an A whose n is one more than m }; Yes, I know this is obvious and it's not always so simple, but I've always found a solution like this to not only work, but actually end up reflecting the problem better. I like the current constructor format: Class(parms) : Base(params), member1(params), member2(params) { ...body... } because it makes it clear that you are constructing objects as opposed to executing statements in the member initialization list. When you are inside curly-braces you shouldn't have to worry whether an object has actually been constructed (which is one reason I believe goto's were restricted in C++). I think introducing two blocks for constructors would lead to errors using objects before they are constructed. Actually, this is already a problem because at least my compiler (Borland C++ 2.0) does not catch the use of an object before it's constructor call in the member initalization list. I don't believe the ARM requires it to be flagged as an error, but it sure would be a nice warning (also remember members are initalized in declaration order, not their order in the member initalization list). Speaking of special warnings for constructors, the use of virtual functions in a constructor would also be nice. Example taken from BC++ bug list at sun.soe.clarkson.edu in the file ~ftp/pub/Turbo-C++/bug-report. class String { char* s; unsigned Len; public: String(const char* p); // char* --> String //... }; String::String(const char* p) : Len(strlen(p)), s(new char[Len+1]) { /////// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ strcpy(s, p); /////// Missed feature: TC++ should warn here } /////// Ex: `Len used before it is initialized' Jamshid Afshar jamshid@emx.utexas.edu