C++: const int and const char* members in classes

C++: const int and const char* members in classes

Post by Eckardt Augenstei » Fri, 19 Mar 1999 04:00:00



Hi everybody!

Maybe someone can give me help on this problem?
Im just writing a class which needs a number of constant numbers and
strings. So I naivley started off like this:

header:
class foo
{
    const unsigned int a_number=7;
    const unsigned char a_string[] =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00};
public:
    a_function(const unsigned int &, const unsigned char* );
    b_function();

Quote:};

code:
...
b_function()
{ ...
    a_function(a_number,a_string);
    ...}

this is fine for the compiler (g++) but produces a linker error
(undefined ref. to a_number, a_string).
Strange to me is that when I use

b_function()
{ ...
unsigned int b_number=a_number;
    a_function(b_number,a_string);
    ...}

theres no error thrown for a_number but the trick doesnt work for the
const char*.  I tried to move the definition into the constructor
foo::foo():a_string={...} , ... {
and chaught some compiler errors, so what is the way its meant to be?
The only workaround I can think of is using static members (didnt try
yet) but shouldnt there be another way?

Thanks in advance for any help / hints!
Eckardt

eckardt _at_ asta.rwth-aachen.de

 
 
 

C++: const int and const char* members in classes

Post by Frank Lenaert » Sat, 20 Mar 1999 04:00:00



> Hi everybody!

> Maybe someone can give me help on this problem?
> Im just writing a class which needs a number of constant numbers and
> strings. So I naivley started off like this:

> header:
> class foo
> {
>     const unsigned int a_number=7;
>     const unsigned char a_string[] =
> {0x00,0x00,0x00,0x00,0x00,0x00,0x00};

IMHO, you are at this point declaring a class, with class constants. These
constants should therefore be static. They can then be initialized in the
.h file (for most compilers, for some compilers the assignment needs to be
done in the .cpp file). Like you did it (above), it aren't class constants
(because they are not static). Non-static attributes are at the object
level while static attributes are at the class level (in fact it is just
mapping C++ semantic meanings to 'OO' meanings, just like "an interface in
C++ can be created by creating an abstract class").

I would have expected the compiler to give you an error (but I never tried
something like your example), but probably the linker is looking for the
values of the object variables you declared and it cannot find it because
the class is not instantiated yet (so the object variables are not
initialized yet because the class' constructor is not called yet)).

Quote:

> public:
>     a_function(const unsigned int &, const unsigned char* );
>     b_function();
> };

> code:
> ...
> b_function()
> { ...
>     a_function(a_number,a_string);
>     ...}

I suppose a_function can be called by its users (because it is public) and
that b_function is calling a_function with the class constants as a default
or so. Maybe it is easier to use parameter initialization i.e.
a_function(const unsigned int a_number = 7, const unsigned char* a_string =
{...}) so that users only have to remember a_function, so that users can
see what the defaults are. Remark that users can only override both
parameters or the last parameter (there is no way to indicate to use for
instance a_number = 8 and a_string = the default one), therefore, you could
put the one users will most probably override as the last one. Can be
tricky sometimes. It's only what I guessed from the example however ...
Quote:

> this is fine for the compiler (g++) but produces a linker error
> (undefined ref. to a_number, a_string).
> Strange to me is that when I use

> b_function()
> { ...
> unsigned int b_number=a_number;
>     a_function(b_number,a_string);
>     ...}

> theres no error thrown for a_number but the trick doesnt work for the
> const char*.  I tried to move the definition into the constructor
> foo::foo():a_string={...} , ... {
> and chaught some compiler errors, so what is the way its meant to be?
> The only workaround I can think of is using static members (didnt try
> yet) but shouldnt there be another way?

> Thanks in advance for any help / hints!
> Eckardt

> eckardt _at_ asta.rwth-aachen.de


 
 
 

C++: const int and const char* members in classes

Post by Lassi Rytel » Sat, 20 Mar 1999 04:00:00


Hi

Think about it, consts that are internal to a class are really static
consts and are allocated only once (not with every instance of object), so
this should be like

class foo {
  static const unsigned int a_number;
  static const unsigned char *a_string;
public:
  int a_function(const unsigned int &, const unsigned char *);
  int b_function();

Quote:};

// code
const unsigned int foo::a_number=7;
const unsigned char *foo::a_string=
            (unsigned char *)"\0x98\0x15\0xde\0xad\0xbe\0xef";
int foo::b_function()
{
 return a_function(a_number, a_string);

Quote:}

int foo::a_function(const unsigned int &a, const unsigned char *b)
{
 return 0;

Quote:}

Not a workaround, this is the way to do it (IMHO)

- Lassi


> Hi everybody!

> Maybe someone can give me help on this problem?
> Im just writing a class which needs a number of constant numbers and
> strings. So I naivley started off like this:

> header:
> class foo
> {
>     const unsigned int a_number=7;
>     const unsigned char a_string[] =
> {0x00,0x00,0x00,0x00,0x00,0x00,0x00};
> public:
>     a_function(const unsigned int &, const unsigned char* );
>     b_function();
> };

> code:
> ...
> b_function()
> { ...
>     a_function(a_number,a_string);
>     ...}

> this is fine for the compiler (g++) but produces a linker error
> (undefined ref. to a_number, a_string).
> Strange to me is that when I use

> b_function()
> { ...
> unsigned int b_number=a_number;
>     a_function(b_number,a_string);
>     ...}

> theres no error thrown for a_number but the trick doesnt work for the
> const char*.  I tried to move the definition into the constructor
> foo::foo():a_string={...} , ... {
> and chaught some compiler errors, so what is the way its meant to be?
> The only workaround I can think of is using static members (didnt try
> yet) but shouldnt there be another way?

> Thanks in advance for any help / hints!
> Eckardt

> eckardt _at_ asta.rwth-aachen.de

 
 
 

C++: const int and const char* members in classes

Post by Michael Schuer » Sat, 20 Mar 1999 04:00:00



> Think about it, consts that are internal to a class are really static
> consts and are allocated only once (not with every instance of object), so
> this should be like

No, they don't need to be static. Const (non-static) data members must
be initialized in the member initialization list of a constructor.

Quote:> class foo {
>   static const unsigned int a_number;

In this case the standard (para. 9.4.2(4)) allows to write

   static const unsigned int a_number = 7;

But the member needs to be defined nevertheless

Quote:> const unsigned int foo::a_number;
> class foo {
>     const unsigned char a_string[] =
> {0x00,0x00,0x00,0x00,0x00,0x00,0x00};

isn't possible, though, as the initializer has to be an _integral_
constant expression.

Michael

--
Michael Schuerig

http://www.schuerig.de/michael/

 
 
 

C++: const int and const char* members in classes

Post by Fred Jackso » Mon, 22 Mar 1999 04:00:00


Lassi's solution works, and here is another solution:

----- begin program source -----

#include <iostream.h>

class Foo
{
public:
  Foo() : Int(7), CharPtr("Hi") { return; }
  void  Print() { cerr << CharPtr << ' ' << Int << endl; return; }
private:
  const int    Int;
  sonst char*  CharPtr;

Quote:};

int main()
{
  Foo  MyFoo;
  MyFoo.Print();
  return 0;

Quote:}

----- end program source -----

This solution init's the const's in the constructor using the init list.
This solution has the following advantages:
1) const's in a class may be initialized to different values for each
   instance (using constructor parameters).
2) It is not necessary to define the const's individually, out of line.

one might consider it ugly, as well as error prone (since they have to
be maintained individually in a separate file) to have to use the out
of line definitions.

I'm not claiming my solution is better; only an alternate you may wish
to consider.

IMHO it stinks that the C++ standard doesn't let you declare inited
const's right in the class declaration, but such is life.


> Hi

> Think about it, consts that are internal to a class are really static
> consts and are allocated only once (not with every instance of object), so
> this should be like

> class foo {
>   static const unsigned int a_number;
>   static const unsigned char *a_string;
> public:
>   int a_function(const unsigned int &, const unsigned char *);
>   int b_function();
> };

> // code
> const unsigned int foo::a_number=7;
> const unsigned char *foo::a_string=
>             (unsigned char *)"\0x98\0x15\0xde\0xad\0xbe\0xef";
> int foo::b_function()
> {
>  return a_function(a_number, a_string);
> }

> int foo::a_function(const unsigned int &a, const unsigned char *b)
> {
>  return 0;
> }

> Not a workaround, this is the way to do it (IMHO)

> - Lassi


> > Hi everybody!

> > Maybe someone can give me help on this problem?
> > Im just writing a class which needs a number of constant numbers and
> > strings. So I naivley started off like this:

> > header:
> > class foo
> > {
> >     const unsigned int a_number=7;
> >     const unsigned char a_string[] =
> > {0x00,0x00,0x00,0x00,0x00,0x00,0x00};
> > public:
> >     a_function(const unsigned int &, const unsigned char* );
> >     b_function();
> > };

> > code:
> > ...
> > b_function()
> > { ...
> >     a_function(a_number,a_string);
> >     ...}

> > this is fine for the compiler (g++) but produces a linker error
> > (undefined ref. to a_number, a_string).
> > Strange to me is that when I use

> > b_function()
> > { ...
> > unsigned int b_number=a_number;
> >     a_function(b_number,a_string);
> >     ...}

> > theres no error thrown for a_number but the trick doesnt work for the
> > const char*.  I tried to move the definition into the constructor
> > foo::foo():a_string={...} , ... {
> > and chaught some compiler errors, so what is the way its meant to be?
> > The only workaround I can think of is using static members (didnt try
> > yet) but shouldnt there be another way?

> > Thanks in advance for any help / hints!
> > Eckardt

> > eckardt _at_ asta.rwth-aachen.de

 
 
 

C++: const int and const char* members in classes

Post by Michael Schuer » Mon, 22 Mar 1999 04:00:00



> class Foo
> {
> public:
>   Foo() : Int(7), CharPtr("Hi") { return; }
>   void  Print() { cerr << CharPtr << ' ' << Int << endl; return; }
> private:
>   const int    Int;
>   sonst char*  CharPtr;
> };
> This solution init's the const's in the constructor using the init list.
> This solution has the following advantages:
> 1) const's in a class may be initialized to different values for each
>    instance (using constructor parameters).

And take up memory for each instance.

Quote:> 2) It is not necessary to define the const's individually, out of line.

Yes, that follows from their not being static.

Quote:> IMHO it stinks that the C++ standard doesn't let you declare inited
> const's right in the class declaration, but such is life.

It does, although only for integral constants. See paragraph 9.4.2(4) in
the ISO standard.

Michael

--
Michael Schuerig

http://www.schuerig.de/michael/