tags:

views:

722

answers:

7

I've got a Car class and a Track class. The Car class constructor takes a road parameter which is supposed to be a 32x32 boolean array. Then I've got a Track class which creates a Car class and is supposed to pass the 32x32 array to it's constructor.

Note that I've simplified the code somewhat by removing irrelevant bits and pieces.

class Car : public WorldObject
{
private:
 bool _road[32][32];

public:
 Car(bool road[32][32])
 {    
  _road = road;
 }
};

class Track : public WorldObject
{
public:
 bool _road[32][32];

 Track()
 {
  Car* _car = new Car(this->_road);
  _car->Position.X = 50;
  _car->Position.Y = 50;
  ChildObjects.push_back(_car);   
 }
};

This won't compile ... I get an error:

Error 1 error C2440: '=' : cannot convert from 'bool [][32]' to 'bool [32][32]'

in the the _road = road; line in the Car constructor.

What am I doing wrong?

A: 

bool road[32][32] is invalid.

There should be a comma in there or the bool should be removed.

stonemetal
Hmmm ... could you be more specific? I believe I'm declaring the array correctly, am I not?
Thorgeir
Comma? Are you sure?
Dmitriy Matveev
Nope, comma won't help here. Neither will removing bool.
Bob Murphy
Well that will teach me to write a response before coffee.
stonemetal
A: 

What about:

memcpy(_road, road, sizeof(road));

Please note, that in C/C++ passing array parameters to a function as you are doing is a bad practice. Use pointers.

Andrejs Cainikovs
Do you really have an idea how is this working? I hope you wanted to paste memcpy(_road, road, sizeof(_road)); Please recheck.
Vadakkumpadath
I've written this code to replace following: _road = road; and my code is right: memcpy(void * destination, const void * source, size_t num);
Andrejs Cainikovs
Vadakkumpadath
Yes, you're right.
Andrejs Cainikovs
I've updated the post.
Andrejs Cainikovs
+2  A: 

In C/C++ every parameter is passed by value except arrays - they are passed by reference. This means in your situation: The signature of your constructor must be read like this:

Car(bool (*road)[32]);

This means: road is a pointer to an array of 32 booleans (to get further informations please read litb's answer to a related question.) Now if you write

_road = road

you copy the value of the pointer road to the variable _road. This is rejected by your compiler because _road isn't a pointer, it's an array of arrays of booleans. For more information about arrays and their values read this. To solve this situation you have to copy the elements of _road manually to road. Something like the following code would solve your problem:

for (int i=0;i<32;++i)
    for (int j=0;j<32;++j)
        _field[i][j] = field[i][j];
phlipsy
Yup. If you really want your 2D array to be something you can pass around, assign using a simple = operator, and so on, you need to wrap it up in a struct or a class. Or, you can do something like "typedef bool road_type[32][32]", and then use road_type to declare road and _road.
Bob Murphy
@Bob: A typedef wouldn't solve the problem. An array stays an array even if it's hidden by a simple typedef. Try it!
phlipsy
I don't see why my answer is down voted two times. Where lies the problem?
phlipsy
@Vadakkumpadath: It's ok. I'll also delete my comment and build the reference to litb's answer in my answer above. It's a pity (but understandable on the other side) that you can't see who down voted your answers...
phlipsy
A: 

Constructor:

Passing an array to constructor in your code is valid. But here is a small problem to take care, you can pass any two dimensional array of type bool with raw size 32. That is your member variable Track::_road shall not produce any error even if it is declared as bool _road[16][32]; This may lead to a memory exception. To avoid this problem, you should specify the function parameter as a reference to an array of dimension 32x32 as follows.

Car(bool (&road)[32][32])
{
}

You may access values inside your function as follows.

_road[i][j] = road[i][j];

You can create a new instance of your class as follows.

Car* _car = new Car(this->_road);

Assignment:

In C/C++, you cannot directly copy an array to another array. You have to copy each and every element individually. You may use a for loop as follows, or some library functions for copying.

for( i = 0; i < 32; i++ )
{
   for( j = 0; j < 32; j++ )
   {
      _road[i][j] = road[i][j];
   }
}
Vadakkumpadath
+3  A: 

To give a minimalistic answer, the only thing that your are doing wrong is that you are trying to assign one array to another array. It really has noting to do with any "passing", as you seem to believe (judging by the subject of your question).

(Yes, I know, the RHS in that problematic assignment is not really an array, but that is a different story).

Remember, in C++ arrays are not assignable and not copy-constructible. For example, this code

int a[10], b[10] = {};
a = b;

is ill-formed for exacly the same reason. You can't assign arrays, regardless of whether you are "passing" them somewhere or not.

The compiler will normally respond with an error message that will involve pointers, which is a consequence of so called "array type decay", which other have already mentioned in previous replies (read up on it).

Since you can't assign arrays, in order to copy your array in this case you either need to do it manually, element by element as in

for (i = 0; i < 32; ++i)
  for (j = 0; j < 32; ++j)
    _road[i][j] = road[i][j];

or you can use 'memcpy' in a few different wys

1. memcpy(_road, road, 32 * 32 * sizeof **_road);
2. memcpy(_road, road, 32 * sizeof *_road);
3. memcpy(_road, road, sizeof _road);

There are more alternative ways to do it.

Note that the aforementioned "array type decay" does take place in this case (as always), but it is transparent to you, i.e. if you perform manual per-element copying you don't need to wory about it al all, as illustrated by the above examples.

AndreyT
A: 

You can't copy arrays like that. Others have already discussed this in more detail, including alternative for-loop individual assignment and memcpy solutions.

Another solution is to wrap your array inside a struct. Struct's can be copied like that.

E.g.:

struct RoadStruct
{
  bool road[32][32];
};

class Car : public WorldObject
{
private:
 RoadStruct _road;

public:
 Car(const RoadStruct & road )
 {    
  _road = road;
 }
};

Though it would be more efficient to copy like this:

public:
 Car(const RoadStruct & road )
   : _road ( road )
 {}

(Of course that creates 2 RoadStruct data sets. If you only wanted one shared array, that could be arranged...)

Mr.Ree
Thanks this method work the best. Coming from c# these c++ things can get a bit frustrating.
Thorgeir
@thorgeir.net: It's a workaround, but it doesn't explain *why* these array things in C/C++ are like this.
phlipsy
+1  A: 

In C++, you can use the standard library to get arrays with more functionality than bool var[n]. Try vector< vector< bool > > road( 32, 32 ); This will be an object that you can pass to functions and assign as you like.

However, conceptually, you might think about linking the _road data from Track to Car rather than copying it, with a vector< vector< bool > > const &_road; and

public:
 Car( vector< vector< bool > > const &road )
  : _road = road;
 {    
 }
};
Potatoswatter