C++将二维数组作为参数传递给类

3

我有一个Car类和一个Track类。Car类的构造函数需要一个道路参数,该参数应该是一个32x32的布尔数组。然后我有一个Track类,它创建了一个Car类,并应该将32x32数组传递给它的构造函数。

请注意,我通过删除不相关的部分来简化了代码。

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);   
 }
};

这段代码无法编译...我遇到了一个错误:

错误1:error C2440: '=' :无法将类型为“bool [][32]”的值赋给类型为“bool [32][32]”的变量

出现在Car构造函数中的 _road = road; 行。

我做错了什么?


(a) 在这里类并不相关--你在函数方面也有同样的问题, (b) "二维"和"二维的"是两个不同的概念, (c) 这很可能是一个重复的内容。 - P Shved
1
在这里查看有关参数衰减的说明:https://dev59.com/m3M_5IYBdhLWcg3wPAnU。 - avakar
6个回答

4

在C/C++中,除了数组以外的所有参数都是按值传递的。这意味着在您的情况下:必须像这样读取构造函数的签名:

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

这意味着: road 是指向一个包含32个布尔值的数组的指针(如需更多信息,请阅读litb在相关问题的回答)。现在,如果您编写
_road = road

您需要将指针road的值复制到变量_road中。但是,您的编译器拒绝了此操作,因为_road不是指针,而是一个布尔数组的数组。有关数组及其值的更多信息,请阅读此文档。要解决这个问题,您需要手动复制_road的元素到road中。像下面的代码一样,可以解决您的问题:
for (int i=0;i<32;++i)
    for (int j=0;j<32;++j)
        _field[i][j] = field[i][j];

如果你真的想让你的二维数组成为可以传递的东西,使用简单的=运算符进行赋值等操作,你需要将其封装在一个结构体或类中。或者,你可以像这样做:“typedef bool road_type[32][32]”,然后使用road_type来声明road和_road。 - Bob Murphy
@Bob:typedef 无法解决问题。即使通过简单的 typedef 隐藏了数组,它仍然是一个数组。试试看! - phlipsy
我不明白为什么我的答案被投了两次反对票。问题出在哪里? - phlipsy
@Vadakkumpadath:没关系。我也会删除我的评论,并在我的回答中引用litb的答案。很遗憾(但从另一方面来说可以理解)你看不到谁对你的回答进行了负评... - phlipsy

3
简洁的回答是,你唯一做错的事情就是试图将一个数组赋值给另一个数组。它与你似乎相信的“传递”没有任何关系(从你的问题主题可以看出)。
(是的,我知道,在那个有问题的赋值语句中,RHS实际上不是一个数组,但那是另外一个故事)。
记住,在C++中,数组是不可赋值和不可复制构造的。例如,这段代码:
int a[10], b[10] = {};
a = b;

由于相同的原因,这是不正确的。无论你是否“传递”数组,都不能对其进行赋值。

编译器通常会返回一个涉及指针的错误消息,这是所谓的“数组类型衰减”的结果,其他人在之前的回复中已经提到了(请查阅相关资料)。

由于不能对数组进行赋值,在这种情况下,为了复制数组,你需要手动逐个元素进行操作,例如:

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

或者您可以以几种不同的方式使用“memcpy”。
1. memcpy(_road, road, 32 * 32 * sizeof **_road);
2. memcpy(_road, road, 32 * sizeof *_road);
3. memcpy(_road, road, sizeof _road);

有更多的替代方法可以实现它。

请注意,前面提到的“数组类型衰减”在这种情况下确实会发生(总是会发生),但对您来说是透明的。也就是说,如果您执行手动逐个元素复制,则无需担心它,如上例所示。


1

构造函数:

在您的代码中将数组传递给构造函数是有效的。但是这里有一个小问题需要注意,您可以传递任何类型为bool且原始大小为32的二维数组。也就是说,即使将其声明为bool _road [16] [32],成员变量Track::_road也不会产生任何错误。但这可能会导致内存异常。为避免此问题,您应将函数参数指定为32x32维数组的引用,如下所示。

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

您可以按照以下方式访问函数内的值。
_road[i][j] = road[i][j];

您可以按照以下方式创建您类的新实例。
Car* _car = new Car(this->_road);

任务:

在C/C++中,你不能直接将一个数组复制到另一个数组。你必须逐个复制每个元素。你可以使用以下的for循环或一些库函数进行复制。

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

1

你不能这样复制数组。其他人已经更详细地讨论了这个问题,包括替代的for循环单独赋值和memcpy解决方案。

另一个解决方案是将数组包装在结构体中。结构体可以像那样被复制。

E.g.:

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

class Car : public WorldObject
{
private:
 RoadStruct _road;

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

虽然这样复制更有效率:

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

(当然这会创建两个RoadStruct数据集。如果你只想要一个共享数组,那也可以安排...)

谢谢,这个方法最有效。作为C#程序员,这些C++的东西有时候真的很让人感到沮丧。 - Thorgeir
@thorgeir.net:这是一个解决方法,但它并没有解释为什么C/C++中的这些数组东西会这样。 - phlipsy

1
在C++中,你可以使用标准库来获取比bool var[n]更多功能的数组。尝试使用vector< vector< bool > > road( 32, 32 );。这将是一个你可以传递给函数并按照你喜欢的方式进行赋值的对象。
然而,在概念上,你可能会考虑将Track中的_road数据与Car进行链接,而不是复制它,使用vector< vector< bool > > const &_road;
public:
 Car( vector< vector< bool > > const &road )
  : _road = road;
 {    
 }
};

-3

bool road[32][32] 是无效的。

这里应该加一个逗号,或者移除 bool。


嗯...你能具体点吗?我相信我声明了数组,不是吗? - Thorgeir
1
不,逗号在这里没有帮助。删除bool也不行。 - Bob Murphy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接