Re: static array initialization in a class

From: John Carson (donaldquixote_at_datafast.net.au)
Date: 03/17/04


To: (Usenet)
Date: 17 Mar 2004 16:03:34 -0500


"wojtek" <vojtekb@wp.pl> wrote in message
news:3c9bee0a.0403150458.80c031a@posting.google.com
> I have a question concerning initialization of static arrays that are
> class fields.
>
> I need a code like this:
>
> class A{
> public:
> int *arr;
> int n;
> A(int nn, const int* narr):n(nn)
> {
> for(int i=0 ; i<n; i++)
> arr[i]=narr[i];
> }
> A(int nn):n(nn){};
> };
>
> class B:public A{
> public:
> const static int init_nums[]={1,2,3};
> const static int init_n=3;
> B():A(init_n, init_nums){
> //..
> }
> };
>
> int main (int argc,char ** args){
> B b;
> }
>
> It does compile but returns a linker error: undefined reference to
> `B::init_nums'.
> Maybe I would understand why, if it returned the same error for
> 'B::init_n'.
> But it doesn't. And it links well when the B's constructor is like
> this:
> B():A(init_n){};
>
> Maybe I miss some 'static' or 'const'?
>
> Could you please help me with this?
>
> Thanks a lot!

This is discussed in section 9.4.2 of the C++ Standard. Static variables are
like functions. Normally, you declare them in the class declaration in the
..h file and then you define and initialise them (once only) in the .cpp
file. Your init_nums fails both because you have not defined it separately
and because you have attempted to initialise it "inline". In fact, because
of the attempt to initialise it "inline", your code should have failed to
compile as well as failing to link.

With functions, there is an exception --- you can define them in the class
declaration and then they become inline. With static variables, there is
also an exception, but it is a different exception, covered in p 4 of
section 9.4.2. If the variable is of static const integer type (but not an
array), then you are allowed to initialise it "inline" in the class
declaration. Whether you still need to define it separately is a little
complicated. This is the passage from the standard:

"If a static data member is of const integral or const enumeration type, its
declaration in the class definition can specify a constant-initializer which
shall be an integral constant expression (5.19). In that case, the member
can appear in integral constant expressions. The member shall still be
defined in a name-space scope if it is used in the program and the namespace
scope definition shall not contain an initializer."

Just what "if it is used in the program" means is not entirely clear.
Stroustrup (TC++PL, p.249) says:

"If (and only if) you use an initialized member in a way that requires it to
be stored as an object in memory, the member must be (uniquely) defined
somewhere."

In any event, the following should work:

class B:public A{
public:
    static const int init_nums[];
    static const int init_n=3;
    B():A(init_n, init_nums){
        //..
    }
};

const int B::init_nums[]={1,2,3};
const int B::init_n;

Note that you must not use the static keyword when defining the static
variable outside of the class declaration and you must not have an
initialiser for init_n since it already has one in the class declaration.

--
John Carson
1. To reply to email address, remove donald 2. Don't reply to email address
(post here instead)
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


Relevant Pages

  • Re: Keeping variable declarations and initialization together
    ... int a = 0; ... If you have an editor that can show you the declaration of a variable from any use of that variable, then it is best to initialise and comment the variable on the declaration line, so that info shows up when the editor shows you the definition line. ... I made sure that the order of arguments, declarations, and conversions matched the order of the information in the packet. ...
    (comp.programming)
  • Re: how to access extern variable from another program ?
    ... >>It is perfectly all right to initialise a variable that is declared as ... provides the location in the source where the compiler ... > is a pure declaration, it introduces the name and tells the compiler ... a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq ...
    (alt.comp.lang.learn.c-cpp)
  • Re: how to access extern variable from another program ?
    ... >>It is perfectly all right to initialise a variable that is declared as ... provides the location in the source where the compiler ... > is a pure declaration, it introduces the name and tells the compiler ... > (and is rarely relevant at all). ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Why cant I initialize member pointers to 0 in class declaration?
    ... it is possible to initialise the pointer at the ... point of declaration, or declare it only when you can initialise it. ... I personally find it good practise ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Why cant I initialize member pointers to 0 in class declaration?
    ... > point of declaration, or declare it only when you can initialise it. ... > to always initialise pointers to some sensible value, ... Josh ...
    (alt.comp.lang.learn.c-cpp)