С++: конструктор / инициализатор для массива?
Я знаком с конструкторами и инициализаторами C++:
class Foo {
int x;
public:
Foo(int _x) : x(_x) {}
};
Foo foo1(37);
Foo foo2(104);
мой вопрос в том, что я должен реализовать класс, который имеет член, который является массивом 3x6. Как бы я сделал что-то подобное вышесказанному?
class Bar {
int coeff[3][6];
public:
// what do I do for a constructor????
};
edit: для простого массива я бы сделал следующее, Я просто не знаю, как это сделать для класса:
static int myCoeffs[3][6] =
{{ 1, 2, 3, 4, 5, 6},
{ 7, 8, 9, 10, 11, 12},
{ 13, 14, 15, 16, 17, 18}};
edit 2: по разным причинам (например, это встроенная система с ограничениями) мне не нужно использовать Boost, поэтому, если это предлагает решение, которое я не могу использовать.
обновление: я не привязан к инициализатор. Это нормально, чтобы сделать это в теле конструктора,и он не должен быть встроенным. Я просто ищу правильный способ построить экземпляр класса, которому нужен массив коэффициентов, не испортив назначение указателя или что-то еще.
6 ответов
ты не можешь. В C++03 вы не можете инициализировать массив в списке ctor-initalization. Однако вы можете сделать это в теле конструктора (технически это больше не инициализация).
что это
struct x
{
int a[4];
x():a({1,2,3,4}) //illegal
{
a[0] = 1;
etc.
}
};
Edit:
после редактирования вопроса вот способ сделать это
#include <algorithm>
struct x
{
int arr[3][4];
x(int (&arg)[3][4])
{
std::copy(&arg[0][0], &arg[0][0]+3*4, &arr[0][0]);
}
};
Я не знаю, звучит ли это слишком очевидно, но почему бы просто не скопировать значения?
class Foo {
static const int X = 3;
static const int Y = 6;
int mCoeff[X][Y];
void setCoeff(int coeff[X][Y]) {
for (int i = 0; i < X; i++) {
for (int j = 0; j < Y; j++) {
mCoeff[i][j] = coeff[i][j];
}
}
}
public:
Foo(int coeff[X][Y]) {
setCoeff(coeff);
}
};
надеюсь, что это помогает. С уважением.
В C++03, поскольку вы не можете инициализировать массив в списке инициализации, вы можете написать общий шаблон функции для заполнения массива заданным массивом, как показано в следующем примере,
template<typename T, size_t N>
void array_fill(T (&dest)[N], T (&src)[N])
{
for ( size_t i = 0 ; i < N ; i++ )
dest[i] = src[i];
}
struct A
{
int a[5];
A(int (&i)[5]) { array_fill(a, i); }
void print()
{
for ( int i = 0 ; i < 5 ; i++ ) cout << a[i] << " ";
}
};
int main() {
int a[5] = {1,2,3,4,5};
A obj(a);
obj.print();
return 0;
}
выход:
1 2 3 4 5
запуск в ideone:http://ideone.com/pFcrv
Ну, тут уже std::copy
который можно использовать также.
вы не можете (в общем) передать произвольный многомерный массив функции на C или C++, как это было бы в Java (я упоминаю Java, потому что именно там ваша история вопросов предполагает, что ваш опыт лежит).
на самом деле нет возможности поддерживать что-либо вроде инициализаторов массива для вашего класса в текущем стандарте, хотя есть некоторые планы изменить это в следующей версии, C++0x.
если вы хотите, чтобы это имело гибкость, скажем, массивов Java (где клиенты могут изменить размер указанного массива, у вас есть несколько вариантов. Первым и лучшим было бы использовать std::vector<>
, который реализует динамический массив, но вы можете быть ограничены на вашей встроенной платформой. Вы также можете реализовать вещи самостоятельно в виде одномерного массива и принять динамический блок памяти. Пример:
class Foo
{
int *theArray_;
unsigned int rows_;
unsigned int cols_;
public:
Foo(int *theArray, int rows, int cols)
: theArray_(theArray)
, rows_(rows)
, cols_(cols)
{ }
void UseTheArray()
{
//Access array[5][6]
theArray[5*cols+6];
}
};
обратите внимание, что в этом случае вызываемый отвечает за передачу памяти. Также рассмотрите возможность использования std::auto_ptr
выше вместо необработанный указатель, чтобы было ясно, кто несет ответственность за уничтожение блока памяти при уничтожении объекта.
Также обратите внимание, что вы не должны использовать имя _x
- имена, начинающиеся с подчеркивания, имеют целую кучу правил, прикрепленных к ним, о которых вы, вероятно, хотите избежать думать.
EDIT: это фрагмент моего первоначального ответа; это неправильно:
Многомерный массив в C++ - это всего лишь один блок памяти. Можно принять многомерный массив, подобный этому, только в одном случае - когда вы заранее знаете точные размеры массива в классе. Тогда вы могли бы написать что-то вроде:
class Foo {
int coeff[3][6];
public:
Foo(int _x[3][6]) : coeff(_x) {}
};
обратите внимание, однако, что размер массива фиксирован и не может быть изменен клиентами вашего класса.
Если вам нужно пойти этим путем, я бы просто пошел на цикл for, повторяющий элементы двумерного массива и инициализирующий их. Или, если вы идете на скорость, что-то вроде memset сделает трюк.
memset(&coeff,0,3*6*sizeof(int))
вы можете сделать это так:
#include <algorithm>
class Bar
{
int coeff[3][6];
public: // what do I do for a constructor????
Bar()
{
int myCoeffs[3][6] =
{
{ 1, 2, 3, 4, 5, 6},
{ 7, 8, 9, 10, 11, 12},
{ 13, 14, 15, 16, 17, 18}
};
std::swap(coeff, myCoeffs);
}
};