A Question about initialization...

D

Denis Remezov

Kai-Uwe Bux said:
For instance:

class X {
public:

static
const std::string str; // declare first.

}; // X

const std::string X::str ( "abcd" ); // initialize later.

Note that, to my great dismay,

class X {
public:

static
const std::string str ( "abcd" ); // in one go? no!

}; // X

does *not* work. Actually, I do not know the reason.

I happened to come across 9.4.2/4 lately. It implies that only const
integral or const enumeration types can be initialised within a class
definition.

Denis
 
D

Denis Remezov

Kai-Uwe Bux said:
Thanks a lot,

that settles it then.

Do you have a guess as what the rational for the provisions of 9.4.2/4
might be? Admittedly, I have not the faintest idea.

[OT & wild speculations]

Just a guess: to make it possible to use integral constants "defined" that
way in integral constant expressions (e.g. array bounds), without the need
for the compiler to look up their values in other translation units (where
they would be eventually defined for real). The utility of non-integral
types is more limited in this respect.

[/OT & wild speculations]

Denis
 
J

JustSomeGuy

I have a class that has a static member variable.

string x;

x should never change during use and should be intialized to "abcd".

How does one do this?
 
P

Pete C.

JustSomeGuy said:
I have a class that has a static member variable.

string x;

x should never change during use and should be intialized to "abcd".

How does one do this?

const string x = "abcd";

- Pete
 
K

Kai-Uwe Bux

JustSomeGuy said:
I have a class that has a static member variable.

string x;

x should never change during use and should be intialized to "abcd".

How does one do this?


For instance:


class X {
public:

static
const std::string str; // declare first.

}; // X

const std::string X::str ( "abcd" ); // initialize later.


Note that, to my great dismay,

class X {
public:

static
const std::string str ( "abcd" ); // in one go? no!

}; // X

does *not* work. Actually, I do not know the reason.


Best

Kai-Uwe
 
V

Victor Bazarov

Pete C. said:
const string x = "abcd";

You cannot do this in a class. You're correct that the member has
to be const, but the initialisation should happen in a constructor.

V
 
V

Victor Bazarov

Pete C. said:
const string x = "abcd";

The declaration and the definition/initialisation has to be
separate for 'string', if it's a member of a class.

Victor
 
P

Pete C.

Victor said:
You cannot do this in a class. You're correct that the member has
to be const, but the initialisation should happen in a constructor.

V

Ah yes, I didn't notice the "class that has a static member variable" part.
Thanks for pointing it out. :)

- Pete
 
V

Victor Bazarov

Pete C. said:
Ah yes, I didn't notice the "class that has a static member variable" part.
Thanks for pointing it out. :)

Actually, you're very quick to respond, I cancelled that message as soon
as I realised that the member variable JustSomeGuy was asking about was
_static_. For that the declaration has to be in the class, but the
definition and initialisation has to be at the namespace level.

V
 
V

Victor Bazarov

Denis Remezov said:
I happened to come across 9.4.2/4 lately. It implies that only const
integral or const enumeration types can be initialised within a class
definition.

And if you read that part of the Standard carefully, you will see that
there is also one more thing: if the static data member is used outside
the class, it still has to be defined at the namespace level.

Victor
 
K

Kai-Uwe Bux

Denis said:
I happened to come across 9.4.2/4 lately. It implies that only const
integral or const enumeration types can be initialised within a class
definition.

Denis

Thanks a lot,

that settles it then.

Do you have a guess as what the rational for the provisions of 9.4.2/4
might be? Admittedly, I have not the faintest idea.


Best

Kai-Uwe
 
J

JustSomeGuy

I seemed to have asked a provocative question...
Seems to me this should have been a straight forward thing one
would want to do with a language...
 
A

Alan Johnson

Kai-Uwe Bux said:
Denis Remezov wrote:




Thanks a lot,

that settles it then.

Do you have a guess as what the rational for the provisions of 9.4.2/4
might be? Admittedly, I have not the faintest idea.


Best

Kai-Uwe

Allowing integral/enum types to be initialized this way allows you to do
some convenient things. For example, consider the following:

class A
{
static const unsigned N ;
int i[N] ; // error.
public :
} ;
const unsigned A::N = 30 ;


But with this allowance, you could do this, instead:


class A
{
static const unsigned N = 30 ;
int i[N] ; // not an error.
public :
} ;
const unsigned A::N ; // Note that this is still needed if you plan on
using N elsewhere.


Further, creeating a constant integral value doesn't necessarily require
that the program *do* anything. That is, The initialization above
probably doesn't produce any executable code. You can't say the same
about, for example, a std::string, where initialization requires a call
to the constructor.

Alan
 
K

Kai-Uwe Bux

Alan said:
Kai-Uwe Bux said:
Denis Remezov wrote:




Thanks a lot,

that settles it then.

Do you have a guess as what the rational for the provisions of 9.4.2/4
might be? Admittedly, I have not the faintest idea.


Best

Kai-Uwe

Allowing integral/enum types to be initialized this way allows you to do
some convenient things. For example, consider the following:

class A
{
static const unsigned N ;
int i[N] ; // error.
public :
} ;
const unsigned A::N = 30 ;


But with this allowance, you could do this, instead:


class A
{
static const unsigned N = 30 ;
int i[N] ; // not an error.
public :
} ;
const unsigned A::N ; // Note that this is still needed if you plan on
using N elsewhere.


Further, creeating a constant integral value doesn't necessarily require
that the program *do* anything. That is, The initialization above
probably doesn't produce any executable code. You can't say the same
about, for example, a std::string, where initialization requires a call
to the constructor.

Alan


Thanks for the explanation,


I am reading the provision of the standard not as an allowance, though,
but as an restriction. I dislike the need to initialize non-integer/enum
constants far away from their definition. Do you know how the fact
that a constructor might get called relates to where in my source I put
the initialization?


Thanks again

Kai-Uwe
 
A

Alan Johnson

Kai-Uwe Bux said:
Alan Johnson wrote:

Kai-Uwe Bux said:
Denis Remezov wrote:



Kai-Uwe Bux wrote:


Note that, to my great dismay,

class X {
public:

static
const std::string str ( "abcd" ); // in one go? no!

}; // X

does *not* work. Actually, I do not know the reason.


I happened to come across 9.4.2/4 lately. It implies that only const
integral or const enumeration types can be initialised within a class
definition.

Denis


Thanks a lot,

that settles it then.

Do you have a guess as what the rational for the provisions of 9.4.2/4
might be? Admittedly, I have not the faintest idea.


Best

Kai-Uwe

Allowing integral/enum types to be initialized this way allows you to do
some convenient things. For example, consider the following:

class A
{
static const unsigned N ;
int i[N] ; // error.
public :
} ;
const unsigned A::N = 30 ;


But with this allowance, you could do this, instead:


class A
{
static const unsigned N = 30 ;
int i[N] ; // not an error.
public :
} ;
const unsigned A::N ; // Note that this is still needed if you plan on
using N elsewhere.


Further, creeating a constant integral value doesn't necessarily require
that the program *do* anything. That is, The initialization above
probably doesn't produce any executable code. You can't say the same
about, for example, a std::string, where initialization requires a call
to the constructor.

Alan



Thanks for the explanation,


I am reading the provision of the standard not as an allowance, though,
but as an restriction. I dislike the need to initialize non-integer/enum
constants far away from their definition. Do you know how the fact
that a constructor might get called relates to where in my source I put
the initialization?


Thanks again

Kai-Uwe

It may help understanding if we pretend to be a compiler (or rather, it
will help me to try to explain it. Please don't get the impression that
I am attempting to insult your ability to understand). As as compiler,
I rarely see a full picture of what is going on. Instead I just see
what is going on within the translation unit I am currently compiling.
So, let's say I'm compiling and encounter the following :

class C
{
static const std::string test("test") ;
} ;

Assuming this were allowed, and did the obvious thing, I only really
have one sensible choice about what to do. I reserve space for the
std::string option (in whatever manner I go about doing things like
that), and generate a call to std::string's constructor, and place it in
whatever place I normally put code that initializes static objects.

Now, let's say that was in a header file, as class declarations often
are. It is quite likely that I'll encounter that same thing again,
reserve more space for it, and generate another call to the constructor,
because how am I to know that that has already been done? But now I've
already violated the definition of a static class member, which is that
there is only one of them. Not to mention, the linker won't know what
to do with multiple symbols called C::test, and will probably spit out a
"multiply defined" error, or something similar.

Why do integral types not have the same problem? For integral types, the
compiler could just treat every subsequent place in which that
constant's value is needed as a literal with that value, much like a
#define (or it could do something much fancier. I really have no clue
what any actual implementations do).

So what is the "proper" place to put initializations of static members?
My opinion on this is that they should go in the same place as the
definitions for the member functions. That is, if you declare "class C"
in C.h, and implement it in C.cpp, then initialization of static members
should go in C.cpp (probably at the very top).

Alan
 
D

Duane Hebert

Kai-Uwe Bux said:
For instance:


class X {
public:

static
const std::string str; // declare first.

}; // X

const std::string X::str ( "abcd" ); // initialize later.

Initialize it in the initializer list of the ctor.

X::X() : str("abcd") {}
 
R

Rick N. Backer

I seemed to have asked a provocative question...
Seems to me this should have been a straight forward thing one
would want to do with a language...


I'm not so sure about what everyone else is saying but, my take would
be that if you know the value of the string now and it is not supplied
as part of the instantiation it would make sense to define it at the
same time it is declared:

class X
{
private:
const static char * = "abcd";

...
};

If it is dynamic I'm not sure how it would eventually work out but I
would attempt to use initialization with the constructor rather than
assignment:

class X
{
private static char * myString;

...
};

X::X(const char * s = "abcd") : myString(s)
{
}

I'm still much of a novice, but I can tell you that the following
won't work (at least it doesn't with Visual C++ 6.0). This last
example is frustrating because it actually appears in an academic text
I am studying right now.

class X
{
private char myString[20];

...
};

X:X(const char * s = "abcd") : myString(s)
{
}

This fails with the following error "X::myString : cannot specify
explicit initializer for arrays."
Ken Wilson
"Just because people don't understand you doesn't mean
you are an artist"
 
J

JustSomeGuy

Rick N. Backer said:
I seemed to have asked a provocative question...
Seems to me this should have been a straight forward thing one
would want to do with a language...


I'm not so sure about what everyone else is saying but, my take would
be that if you know the value of the string now and it is not supplied
as part of the instantiation it would make sense to define it at the
same time it is declared:

class X
{
private:
const static char * = "abcd";

...
};

If it is dynamic I'm not sure how it would eventually work out but I
would attempt to use initialization with the constructor rather than
assignment:

class X
{
private static char * myString;

...
};

X::X(const char * s = "abcd") : myString(s)
{
}

I'm still much of a novice, but I can tell you that the following
won't work (at least it doesn't with Visual C++ 6.0). This last
example is frustrating because it actually appears in an academic text
I am studying right now.

class X
{
private char myString[20];

...
};

X:X(const char * s = "abcd") : myString(s)
{
}

This fails with the following error "X::myString : cannot specify
explicit initializer for arrays."
Ken Wilson
"Just because people don't understand you doesn't mean
you are an artist"


I'm not sure but I get the feeling you're impression of static
is that of a C programmer... Static has a different meaning in C++
(I of course am just assuming)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top