what's wrong with declaration of array in class

T

thomas

Hi,
-------------code----------
#include<iostream>
using namespace std;

class maze{
public:
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
void print(){
cout<<"hello"<<endl;
}
};

int main(){
maze ins;
ins.print();
}
------------code-----------------

The code cannot compile because of the declaration of the array "dir".
But I don't get it? why is that?
 
A

Alf P. Steinbach

* thomas:
Hi,
-------------code----------
#include<iostream>
using namespace std;

class maze{
public:
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
void print(){
cout<<"hello"<<endl;
}
};

int main(){
maze ins;
ins.print();
}
------------code-----------------

The code cannot compile because of the declaration of the array "dir".
But I don't get it? why is that?

AFAIK there's no good reason, except historical accident, why the language is
that way.

In C++98 the only data members you can initialize directly in the declaration
are static const of integral or enumeration type (I'm using that standard's
terminology here -- as far as I'm concerned an enum is very integral!).

That means that in C++98 you have the same problem almost no matter the type, e.g.

class Amazing
{
double x = 5; // Nah!
};

One way out is to use a constructor initializer list, like

class InstanceData
{
private:
double x;
public:
InstanceData(): x( 5 ) {}
};

If, however, the data is constant and the same for all instances, as it seems
your 'dir' array will be, then you can declare it static const,

class ClassData
{
private:
static double const x;
public:
// Whatever
};

double const ClassData::x = 5;

where the last line, the value definition, needs to be in exactly one
compilation unit and exactly once, i.e., don't put it in a header file.

The corresponding for your maze:

class Maze
{
private:
static int const dir[4][2];
public:
// Whatever.
};

int const Maze::dir[4][2] =
{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

However, I suggest defining a class Point to handle those (x,y) values, instead
of doing indexing or whatever -- it will save much work. :)


Cheers & hth.,

- Alf
 
T

thomas

AFAIK there's no good reason, except historical accident, why the language is
that way.

In C++98 the only data members you can initialize directly in the declaration
are static const of integral or enumeration type (I'm using that standard's
terminology here  --  as far as I'm concerned an enum is very integral!).
Oh, I see. In my opinion, maybe the designer think that only data
stored globally (like static) can be initialized in a class. Local
data should be initialized in a ctor. But I don't understand why he
would take only static const integeral type specially. It just makes
more confusions.
That means that in C++98 you have the same problem almost no matter the type, e.g.

   class Amazing
   {
       double x = 5;   // Nah!
   };

One way out is to use a constructor initializer list, like

   class InstanceData
   {
   private:
       double x;
   public:
       InstanceData(): x( 5 ) {}
   };

If, however, the data is constant and the same for all instances, as it seems
your 'dir' array will be, then you can declare it static const,

   class ClassData
   {
   private:
       static double const x;
   public:
       // Whatever
   };

   double const ClassData::x = 5;

where the last line, the value definition, needs to be in exactly one
compilation unit and exactly once, i.e., don't put it in a header file.
Yes. But I don't want to declare a variable and bother going somewhere
else to do initialization.
The corresponding for your maze:

   class Maze
   {
   private:
       static int const dir[4][2];
   public:
       // Whatever.
   };

   int const Maze::dir[4][2] =
       {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

However, I suggest defining a class Point to handle those (x,y) values, instead
of doing indexing or whatever  --  it will save much work. :)
What I need is an const array of int. By const, I really mean that
they will not be changed. And I expect they won't be used otherwhere.
That's why I want them to be in the class scope. But the C++ standard
makes it rather messy.
 
N

Neelesh

AFAIK there's no good reason, except historical accident, why the language is
that way.
In C++98 the only data members you can initialize directly in the declaration
are static const of integral or enumeration type (I'm using that standard's
terminology here  --  as far as I'm concerned an enum is very integral!).

Oh, I see. In my opinion, maybe the designer think that only data
stored globally (like static) can be initialized in a class. Local
data should be initialized in a ctor. But I don't understand why he
would take only static const integeral type specially. It just makes
more confusions.




That means that in C++98 you have the same problem almost no matter the type, e.g.
   class Amazing
   {
       double x = 5;   // Nah!
   };
One way out is to use a constructor initializer list, like
   class InstanceData
   {
   private:
       double x;
   public:
       InstanceData(): x( 5 ) {}
   };
If, however, the data is constant and the same for all instances, as it seems
your 'dir' array will be, then you can declare it static const,
   class ClassData
   {
   private:
       static double const x;
   public:
       // Whatever
   };
   double const ClassData::x = 5;
where the last line, the value definition, needs to be in exactly one
compilation unit and exactly once, i.e., don't put it in a header file.

Yes. But I don't want to declare a variable and bother going somewhere
else to do initialization.
The corresponding for your maze:
   class Maze
   {
   private:
       static int const dir[4][2];
   public:
       // Whatever.
   };
   int const Maze::dir[4][2] =
       {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
However, I suggest defining a class Point to handle those (x,y) values, instead
of doing indexing or whatever  --  it will save much work. :)

What I need is an const array of int.

What you _really_ need is an "array of const int". an array is always
"const", you can never make an array variable hold another array.

By const, I really mean that
they will not be changed. And I expect they won't be used otherwhere.
That's why I want them to be in the class scope.

Giving a definition for a static member variable outside the class
doesn't change its scope.
 
T

thomas

What you _really_ need is an "array of const int". an array is always
"const", you can never make an array variable hold another array.
Yeah. Good correction.

Giving a definition for a static member variable outside the class
doesn't change its scope.- Hide quoted text -
Yes. But I have to take care of the member initialization outside the
class. I just feel I am fitting my feet to another one's shoes. It's
painful especially when there's no good reason.
 
A

Alf P. Steinbach

* thomas:
Yes. But I have to take care of the member initialization outside the
class. I just feel I am fitting my feet to another one's shoes. It's
painful especially when there's no good reason.

It's just textual placement.

It doesn't affect the scoping.

There are some workarounds though, like ...

class Maze
{
private:
static int dir( int which, int xy )
{
static int const dirData[4][2] =
{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
return dirData[which][xy];
}
public:
// Whatever
};

.... which allows you to have it all in a header file, if that's what you want.


Cheers & hth.,

- Alf
 

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

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,828
Latest member
LauraCastr

Latest Threads

Top