C ++ Передача двумерных массивов в качестве параметров классам - PullRequest
2 голосов
/ 10 октября 2009

У меня есть класс автомобилей и класс треков. Конструктор класса 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 ошибка C2440: '=': невозможно преобразовать из 'bool [] [32]' в 'bool [32] [32]'

на дороге _road =; линия в конструкторе автомобилей.

Что я делаю не так?

Ответы [ 6 ]

4 голосов
/ 10 октября 2009

В C / C ++ каждый параметр передается по значению, кроме массивов - они передаются по ссылке. В вашей ситуации это означает: подпись вашего конструктора должна читаться так:

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

Это означает: road - это указатель на массив из 32 логических значений (для получения дополнительной информации, пожалуйста, прочитайте ответ на соответствующий вопрос.) Теперь, если вы напишите

_road = road

Вы копируете значение указателя road в переменную _road. Это отклонено вашим компилятором, потому что _road не указатель, а массив массивов логических значений. Для получения дополнительной информации о массивах и их значениях прочитайте this . Чтобы решить эту ситуацию, вы должны скопировать элементы _road вручную в road. Что-то вроде следующего кода решит вашу проблему:

for (int i=0;i<32;++i)
    for (int j=0;j<32;++j)
        _field[i][j] = field[i][j];
3 голосов
/ 10 октября 2009

Чтобы дать минималистичный ответ, единственное, что вы делаете неправильно, это то, что вы пытаетесь присвоить один массив другому массиву. Это действительно имеет отношение к любому «прохождению», как вы, кажется, верите (судя по предмету вашего вопроса).

(Да, я знаю, 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 голос
/ 10 октября 2009

В C ++ вы можете использовать стандартную библиотеку для получения массивов с большей функциональностью, чем bool var[n]. Попробуйте vector< vector< bool > > road( 32, 32 ); Это будет объект, который вы можете передавать функциям и назначать по своему усмотрению.

Однако, концептуально, вы можете подумать о связывании данных _road с Track с Car вместо их копирования с vector< vector< bool > > const &_road; и

public:
 Car( vector< vector< bool > > const &road )
  : _road = road;
 {    
 }
};
1 голос
/ 10 октября 2009

Вы не можете копировать подобные массивы. Другие уже обсуждали это более подробно, включая альтернативные индивидуальные назначения для цикла и решения memcpy.

Другое решение - заключить ваш массив в структуру. Структуры можно копировать так.

например:.

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

(Конечно, это создает 2 набора данных RoadStruct. Если вам нужен только один общий массив, это можно организовать ...)

1 голос
/ 10 октября 2009

Конструктор:

Передача массива в конструктор в вашем коде допустима. Но здесь есть небольшая проблема: вы можете передать любой двумерный массив типа bool с необработанным размером 32. То есть ваша переменная-член Track :: _ road не выдаст никакой ошибки, даже если она объявлена ​​как bool _road [16] [32]; Это может привести к исключению памяти. Чтобы избежать этой проблемы, вы должны указать параметр функции как ссылку на массив измерения 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];
   }
}
0 голосов
/ 10 октября 2009

дорога bool [32] [32] недействительна.

Там должна быть запятая или bool должен быть удален.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...