[comp.lang.c++] Class member initialization proposal

ronen@cit-vax.Caltech.Edu (Ronen Barzel) (04/11/90)

WHAT DO I WANT?

An extra capability in C++: the ability to specify initializations
for class members within the class definition, as part of the member
declaration.  Thus, for example, I would like the following to be legal:


    OLD					NEW
    ----------------------		------------------------------
    class A {				class A {
	char *ptr;			    char *ptr = 0;
	const int n;			    const int n = 3;
	class B &bref;			    class B &bref = * new class C;
	double f;			    double f = 1.5;
	int i;				    int i;
	A();				    A();
	A(int);				    A(int);
    };					};
    A::A() : 				A::A()
	ptr(0), n(3),			{ /* body */ }
	bref(* new class C),
	f(1.5)
	{ /* body */ }

    A::A(int j) :			A::A(int j) : i(j)
	ptr(0), n(3)			{ /* body */ }
	bref(* new class C),
	f(1.5),
	i(j)
	{ /* body */ }


Essentially, the compiler would prepend the class-specified initializations
to whatever is listed in the constructor initialization list.


WHY DO I WANT THIS?

Three related reasons:

    a. I often have pointer members that I want initialized to 0
       (e.g. "ptr" above); it's easiest to just specify the 0 where
       the pointers are declared.

    b. More generally, it seems cleaner to be able to specify the
       initialization of a variable in the same place it's declared;
       as is, if I change around what the members of a class, I then
       have to go somewhere else in the file to update the initializations.

    c. Most important:  When a class has several constructors, the
       initialization must be duplicated for each constructor; this is
       clearly error-prone, since any changes must be repeated for each
       constructor.  To minimize the problems, I often write code like this:

	    #define A_INIT	ptr(0), n(3), B(* new class C), f(1.5)

	    A::A() : A_INIT { ... }
	    A::A(int j) : A_INIT, i(j) { ... }
	    A::A(char *s) : A_INIT { ... }

       This seems a little klunky, however.


COROLLARY ISSUES:

Some relatively minor questions arise.

    a. Order of initialization?  Perhaps the initializations would
       happen in order of appearance.  It would be nice if the result
       of an earlier initialization could be used in a later one.

    b. Overriding initializations via the member initialization list?  
       If a constructor tries to initialize something that has an initialization
       in the class definition, it could be considered illegal; more convenient,
       however, might be to have the new initialization override.  E.g.

	    OLD				NEW
	    ----------------------	------------------------------
	    A::A(int m, int j) :	A::A(int m, int j) : n(m), i(j)
		ptr(0), n(m),		{ /* body */ }
		bref(* new class C),
		f(1.5),
		i(j)
		{ /* body */ }

    c. Scope for expressions?  I guess the scope would be the same as for
       the member initialization list of a constructor with no arguments:
       i.e. "this", class members, and file-scope items.

COMMENTS:

This feature seems to me to have everything going for it -- it's useful,
backwards compatible, doesn't add new syntax, ought to be easy to implement.
Before I twist my arm patting myself on the back, how do all of you "out there"
feel about it?  Comments, counter-proposals?  Am I a dope?  Is this old hat?
Does Brand X C++ already support this?

-Ronen Barzel
 ronen@csvax.caltech.edu

ronen@cit-vax.Caltech.Edu (Ronen Barzel) (04/11/90)

In article <14560@cit-vax.Caltech.Edu> I write:
>                         ...the ability to specify initializations
>for class members within the class definition, as part of the member
>declaration....
>
>Does Brand X C++ already support this?

I have been told that g++ supports this feature.  Out of curiousity,
are there any other C++ implementations that support enchancements
(or other language differences) over the AT&T2.0/Stroupstrup/Lippman
standard?  

-Ronen

horstman@sjsumcs.sjsu.edu (Cay Horstmann) (04/13/90)

In article <14560@cit-vax.Caltech.Edu> ronen@cit-vax.Caltech.Edu (Ronen Barzel) writes:
>WHAT DO I WANT?
>
>An extra capability in C++: the ability to specify initializations
>for class members within the class definition, as part of the member
>declaration.  Thus, for example, I would like the following to be legal:
>
>
>    OLD					NEW
>    ----------------------		------------------------------
>    class A {				class A {
>	char *ptr;			    char *ptr = 0;
>	const int n;			    const int n = 3;
...
>	A();				    A();
>	A(int);				    A(int);
>    };					};
...

I don't think this is so great. The only benefit would be to give the
compiler a hint to factor out code common to all constructors. But you
could do that manually with a member function. 

HOWEVER, for static const this would indeed be very desirable:

	class Table
	{	static const int SIZE = 20;
		Whatnot* t[ SIZE ];
	// ...
	};

Whatever you do, please do not post back that I could use 
a local enum { SIZE = 20 }. 

Cay

ronen@cit-vax.Caltech.Edu (Ronen Barzel) (04/14/90)

In article <1990Apr13.064548.1133@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes:
>                             ...The only benefit would be to give the
>compiler a hint to factor out code common to all constructors. But you
>could do that manually with a member function. 

You can't do it in all cases.  From Lippman, sec 6.1 p.243: 
"The member initialization list is the only mechanism by which const
and reference class data members can be initialized."  Thus const and
reference initializations can't be factored out into a member function.

>HOWEVER, for static const this would indeed be very desirable:
I agree.  Even for static but non-const.  In summary, I think it's
desirable to specify an initialization for anything as part of (or at
least along with) its definition.  [Anybody care to argue with this claim?]

Along the same lines, it would be nice to specify default parameters
to base class constructors.  Again, this is something that can't be
factored out into a member function.  e.g.:

    OLD					NEW
    ----------------------		------------------------------
    class A : public B {		class A : public B(3,"foo") {
	A();				    A();
    };					};
    A::A() : B(3,"foo")			A::A()
    { /* body */ }			{ /* body */ }

Does g++ support this too?

-Ronen