2013-06-01 4 views
-1

Я работал над некоторым кодом для задания, и у меня проблема с вложенными шаблонами.Внедрение многомерных массивов

мне нужен следующий код для создания 3 элемента массива из 3-х элементов массивов (вроде как Int б [3] [3]):

Array< Array<int> > b(3);

Вот соответствующие части моего массива .h:

template <class T> 
class Array{ 
    public: 
    Array() : size(0){ data = NULL; } 

    Array(int s) : size(s) { data = new T[size]; } 

    Array(const Array & a) : size(a.length()) { 
     data = new T[a.length()]; 
     for(int i = 0; i < a.length(); ++i) 
     data[i] = a[i]; 
    } 

~Array(){ delete[] data; } 

T & operator[](int i) { 
    if (i >= 0 && i < size){ 
     return data[i]; 
    } else { 
     throw ArrayOutOfBounds(i); 
    } 
} 

T operator[](int i) const{ 
    if (i >= 0 && i < size){ 
     return data[i]; 
    } else { 
     throw ArrayOutOfBounds(i); 
    } 
} 

Array<T> & operator=(const Array<T> &a){ 
    if(this == &a) return *this; 
    delete[] data; 
    data = new T[a.length()]; 
    for(int i = 0; i < a.length(); ++i) 
     data[i] = a[i]; 
    size = a.length(); 
} 

    int length() const { return size; } 

    // Members 

    private: 
    int size; 
    T * data; 
} 

Update 6/1 полный код драйвера:

// Test driver for generic Array object with assignment and bounds checking 

    #include "Array.h" 

int main() { 
    Array<int> a1(10); 
for (int i = 0; i < a1.length(); ++i) 
     a1[i] = i * i; 
Array<int> a2 = a1; 
try { 
    for (int i = 0; i <= a2.length(); ++i) 
     cout << a2[i] << " "; 
    cout << endl; 
} 
catch (const ArrayOutOfBounds & e) { 
    cout << endl << "ArrayOutOfBounds index=" << e.index << endl; 
} 
Array< Array<int> > b(3); 
for (int i = 0; i < b.length(); ++i) { 
    for (int j = 0; j < b[i].length(); ++j) 
     b[i][j] = i*b[i].length() + j; 
} 
for (int i = 0; i < b.length(); ++i) { 
    cout << "b[" << i << "]= "; 
    for (int j = 0; j < b[i].length(); ++j) 
     cout << b[i][j] << " "; 
    cout << endl; 
} 

Array<const char *> c(3); 
c[0] = "moe"; c[1] = "curly"; c[2] = "larry"; 
Array<const char *> d(10); 
d = c; 
for (int i = 0; i < d.length(); ++i) 
    cout << "d[" << i << "]=" << d[i] << " "; 
cout << endl; 

return 0; 
}  

Ожидаемый результат:

0 1 4 9 16 25 36 49 64 81 
ArrayOutOfBounds index=10 
b[0]= 0 1 2 
b[1]= 3 4 5 
b[2]= 6 7 8 
d[0]=moe d[1]=curly d[2]=larry 

Update 6/2

раствора на Guillaume, вот метод изменения размера я использовал:

Array<T> & resize(int newsize){ 
    delete[] data; 
    data = new T[newsize]; 
    size = newsize; 
    for(int i = 0; i < size; ++i) 
     init(data[i], size); 
} 

Рекурсивного изменение размера работает для более высоких размерностей, например as Array< Array< Array<int> > > q(3);

+0

Возможно, вы вызываете 'delete []' на неинициализированный указатель. – chris

+0

По крайней мере, вам нужно составить план, как передать второе измерение конструктору. – BlueWanderer

+0

Для чего это стоит [ваш код не падает на Ideone] (http://ideone.com/9cOHRT). – djf

ответ

2

На основании кода, вы вставили, это не должно падать. Вы забыли деструктора? У вас должен быть деструктор, который удаляет память. Когда он у вас есть, вы должны убедиться, что данные инициализированы на nullptr (или NULL), поэтому он не сбой при удалении пустого массива.

Но ваш подход в замешательстве. Предполагается ли, что размер массива определяется во время выполнения или во время компиляции? int b[3][3] определяется во время компиляции. Если вы этого хотите, вы должны указать размер аргумента шаблона, например std::array в C++ 11, см. http://en.cppreference.com/w/cpp/container/array

Если вы хотите уменьшить размер во время выполнения, вам понадобится метод изменения размера, чтобы определить размер второе измерение.

EDIT: На основе кода драйвера вам нужно сделать что-то другое в конструкторе (передавая int в T, если T является массивом). Честно говоря, это похоже на ошибку. Этот вид спецификации делает его очень трудно описать то, что конструктор делать (вызов CTOR по умолчанию для всех типов T для массива, за исключением)

я бы что-то вроде этого:

private: 
template <typename U> 
void init(U&, int) {} 

template <typename U> 
void init(Array<U>& a, int sz) 
{ 
    a.resize(sz); 
} 

public: 
Array(int s) : size(s) { 
    data = new T[size]; 
    for (int i = 0 ; i < size; ++i) { 
     init(data[i], s); 
    } 
} 

Это работает, но это некрасиво. Если вы можете использовать C++ 11, вы можете сделать что-то приятнее с помощью std :: enable_if

+0

Ahh да, благодаря причине segfault был неинициализированным указателем. Основываясь на коде драйвера, я думаю, что размер должен быть определен во время выполнения. Метод изменения размера звучит разумно, но у меня возникают проблемы с сопряжением массива контейнера с элементами массива. Я пытаюсь проверить typeids класса шаблона с Array (в конструкторе, который принимает int), чтобы увидеть, совпадают ли они, а затем построить массив. Это кажется грубой силой и проблематичным, знаете ли вы, что лучше? – Cam

+0

@CameronJuarez Добавить 'T & operator [] (int i) {return data [i]; } '. Затем используйте это для вызова resize() 'for (int i = 0; i <3; ++ i) {b [i] .resize (3); } ' – Guillaume

+0

Правильно, я добрался так далеко, но как я могу отличить элемент Array от элемента, отличного от Array? например 'b [i] .resize (n)' не имеет смысла, если b является массивом примитивов. – Cam

Смежные вопросы