[comp.lang.c++] Constant member variables in TC++

ahuttune@niksula.hut.fi (Ari Juhani Huttunen) (11/12/90)

An example class:

class X {
const int const_int;
};

Gives a warning: constant field not initialized.

class X {
const int const_int = 5;
};

Gives an error: can't initialize a field.

So???????
--
  ___  ___  ___  ___  ___  ___  ___  ___  ___  
__I I__I I__I I__I I__I I__I I__I I__I I__I I  Thank you 
 Ari Huttunen    (ahuttune@niksula.hut.fi)  I   for not smoking!
____________________________________________I    <Robocop>

bjaspan@athena.mit.edu (Barr3y Jaspan) (11/12/90)

In article <AHUTTUNE.90Nov11180721@wonderwoman.hut.fi>, ahuttune@niksula.hut.fi (Ari Juhani Huttunen) writes:
|> class X {
|> const int const_int;
|> };
|> 
|> Gives a warning: constant field not initialized.
|> 
[but initializing it...]
|>
|> Gives an error: can't initialize a field.

This is an annoying side-effect of separate compilation and the semantics of
const variables.  The contraints:

1) By definition, a const variable cannot be assigned to.  In the first
example, you aren't initializing it, which means you are going to have a
"constant" garbage value.

2) You can't put an initialization in a header file because then the compiler
would have no way of knowing WHICH of the many .C files it was #included in
was the "main .C file" in which the initialization should take place --
therefore, the initialization would probably take place more than once.


Hmmm... now that I think about (2), it doesn't seem right.  In this particular
case, the compiler could easily do the initialization as implicit behavior in
every constructor (assuming it did the initialization at all instead of just
replacing all occurrences of that field with an immediate constant).

Anyway, the only way I know of to get around this problem is to declare an
enum with the constant you want.  It's a kludge but it works.  So, for example,

class X {
	enum { const_int = 10 };

	int by_the_way_this_works_too[const_int];
};

will make "const_int" be a constant 10 and even declares a constant-length
array in the process (which there is also no other way to do).  Note that
enums do not have to be named.

-- 
Barr3y Jaspan, bjaspan@mit.edu

starr-page@cs.yale.edu (Page Starr) (11/12/90)

In article <AHUTTUNE.90Nov11180721@wonderwoman.hut.fi>,
ahuttune@niksula.hut.fi (Ari Juhani Huttunen) writes:
|> An example class:
|> 
|> class X {
|> const int const_int;
|> };
|> 
|> Gives a warning: constant field not initialized.
|> 
|> class X {
|> const int const_int = 5;
|> };
|> 
|> Gives an error: can't initialize a field.
|> 
|> So???????
|> --

constant members in classes are initialized in the member initialization
list.
So the correct solution here would be:

class X {
const int const_int;
X(): const_int(5) {;}
};

If you don't want a constant in each object, the correct solution would
be:

class X2{
static const int const_int2;
};

and then in one .C file:

const int X2::const_int2 = 5;

------------------------------------------------------------------------
------
CSnet:   starr@cs.yale.edu			BITNET:  starr@yalecs.BITNET
ARPAnet: starr%cs.yale.edu@relay.cs.net		Phone:	 (203)432-1215
USmail:  Page Starr, Box 2158 Yale Station, New Haven, CT  06520

marc@dumbcat.sf.ca.us (Marco S Hyman) (11/12/90)

In article <1990Nov11.181752.8098@athena.mit.edu> bjaspan@athena.mit.edu
(Barr3y Jaspan) writes:
    In article <AHUTTUNE.90Nov11180721@wonderwoman.hut.fi>,
    ahuttune@niksula.hut.fi (Ari Juhani Huttunen) writes:
    |> class X {
    |> const int const_int;
    |> };
    |> 
    |> Gives a warning: constant field not initialized.
    |> 
    [but initializing it...]
    |>
    |> Gives an error: can't initialize a field.
    
    Anyway, the only way I know of to get around this problem is to declare
    an enum with the constant you want.  It's a kludge but it works.  So,
    for example,

    class X {
    	enum { const_int = 10 };
    
    	int by_the_way_this_works_too[const_int];
    };
    
    will make "const_int" be a constant 10 and even declares a constant-length
    array in the process (which there is also no other way to do).  Note that
    enums do not have to be named.

Uh, this is the hard way.  The requirement is that the constant members of
a class be initialized when an object is created.  There is a syntax to
support this.  Try:

	class X {
	  private:
	    const int const_int;
	  public:
	    X(int i) : const_int(i) {};
	};

This compiles with cfront 2.0 without error.  See section 12.6 of the ARM,
especially the example on page 290.

// marc


-- 
// marc@dumbcat.sf.ca.us
// {ames,decwrl,sun}!pacbell!dumbcat!marc

pcg@cs.aber.ac.uk (Piercarlo Grandi) (11/13/90)

On 11 Nov 90 17:07:21 GMT, ahuttune@niksula.hut.fi (Ari Juhani Huttunen) said:

ahuttune> class X {
ahuttune> const int const_int;
ahuttune> };

ahuttune> Gives a warning: constant field not initialized.

Perfectly correct. If you had RTFM with care, it would have emerged
that it is now possible to initialize data members in the cosntructor,
and that indeed this is the recommended way of doing so, and even more
relevant, it is the only way to initialize constant non static data
members.

I do not like the ad-hoc rules for constructors like this, but such is
the language. Rewrite your exmaple as:

	struct s { const int c; s(value) : c(value) {}; };
--
Piercarlo Grandi                   | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk