Двумерный массив с использованием шаблонов - PullRequest
6 голосов
/ 22 декабря 2011

Я пытаюсь реализовать динамический массив:

template <typename Item>
class Array {
private:
    Item *_array;
    int _size;
public:
    Array();
    Array(int size);
    Item& operator[](int index);
};

template <typename Item>
Array<Item>::Array() {
    Array(5);
}

template <typename Item>
Array<Item>::Array(int size) {
    _size = size;
    _array = new Item [size];

    for (int i = 0; i < size; i++)
        cout << i << " " << _array[i] << " " << &_array[i] << endl;
}

template <class Item>
Item& Array<Item>::operator[](int index) {
    if (index < 0 || index > _size-1)
        cout << "this: " << this << ". Index out of range" << endl;

    return _array[index];
}

При использовании, как это, он работает, как ожидалось, т.е. печатает 5:

Array< int > testArray(5);
testArray[0] = 5;
cout << testArray[0] << endl;

Однако я бынравится использовать класс для двумерного динамического массива.Я думал, что следующее будет просто волшебно работать и печатать 5 ...

Array< Array<int> > testArray(5);
testArray[0][0] = 5;
cout << testArray[0][0] << endl;

... но это не работает.Сбой при попытке установить значение на [0] [0].Отладчик показывает мне, что this имеет _size, установленный в 0 и _array в NULL.this в этой точке указывает на первый элемент _array последнего созданного экземпляра Array.

Одна из вещей, которые я не получаю, это когда внутренний массив вызывает свой конструктор.Проходя по коду, я вижу, что Array(int size) вызывается один раз и Array() пять раз.Я хотел бы создать внутренний массив с определенным размером, но использование Array< Array<int>(10) > testArray(5) не компилируется.

Не могли бы вы дать мне некоторое представление об этом?Кажется, я пока не могу обернуться вокруг шаблонов ...

Ответы [ 3 ]

6 голосов
/ 22 декабря 2011

Вы не можете связывать вызовы конструктора в C ++. Ваша первая реализация конструктора ничего не делает, поэтому 5 экземпляров, содержащихся в родительском Array, в конечном итоге неинициализируются, что приводит к неопределенному поведению.

Чтобы исправить, вы можете либо добавить значение по умолчанию к параметру size другого конструктора, либо выделить логику инициализации в отдельной (закрытой) функции и вызвать ее из обоих конструкторов.

EDIT : Причина, по которой первый конструктор ничего не делает, заключается в том, что строка

Array(5)

не вызывает конструктор текущего экземпляра, а вместо этого выделяет новый (неназванный) временный Array экземпляр, который немедленно уничтожается в конце строки.

3 голосов
/ 22 декабря 2011

Используйте значение по умолчанию для конструктора, чтобы вызывать его без аргумента, т.е. Array(int index = 5);

Пожалуйста, проверьте это: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3

Может ли один конструктор класса вызвать другой конструктортот же класс для инициализации этого объекта?

1 голос
/ 22 декабря 2011

Вы не можете вызвать другого ctor с вашего ctor по умолчанию.Если вы хотите иметь значение по умолчанию, вы можете объединить два в одно.

template <typename Item>
Array<Item>::Array(int size = 5) {
    _size = size;
    _array = new Item [size];

    for (int i = 0; i < size; i++)
        cout << i << " " << _array[i] << " " << &_array[i] << endl;
}

Однако, если вы все еще предпочитаете иметь два ctor, вы можете переместить реализацию в частную функцию _setup, которую можно использовать.из обоих вот так.

template <typename Item>
Array<Item>::Array() {
    _setup(5);
}

template <typename Item>
Array<Item>::Array(int size) {
    _setup(size);
}

template <typename Item>
void Array<Item>::_setup(int size) {
    _size = size;
    _array = new Item [size];

    for (int i = 0; i < size; i++)
        cout << i << " " << _array[i] << " " << &_array[i] << endl;
}

Отредактировано для удаления недопустимого инициализатора для нового массива.

...