Форум программистов, компьютерный форум CyberForum.ru

Перегрузка двойного индексного оператора - C++

Восстановить пароль Регистрация
Другие темы раздела
C++ С++ Найти символ в строке http://www.cyberforum.ru/cpp-beginners/thread795334.html
Задача:напишите программу,подсчитывающую количество определённой буквы в строке.строка и буква вводится пользователем. сам мучаюсь третий день не могу понять как сделать нормально.
C++ Указатель и ссылка Почему выгодней использовать указатель а не ссылку при использовании массивов? http://www.cyberforum.ru/cpp-beginners/thread795331.html
Алгоритмы сортировки: прямые, улучшенные (Сортировка с помощью включений с уменьшающимися расстояниями (сортировка Шелла)) C++
Задание 2. Сортировка с помощью включений с уменьшающимися расстояниями (сортировка Шелла). Методические указания к выполнению задания 2 Описать алгоритм сортировки. Проанализировать его эффективность. Написать программу сортировки данных с использованием указанного алгоритма. Сравнить эффективность улучшенного алгоритма с прямым алгоритмом из задания 1. Зарание большое спасибо за...
Для сохранения данных задания 1 использовать динамическую структуру – бинарное дерево. Выбрать все записи о невостребованных учебниках C++
Задание 2. Для сохранения данных задания 1 использовать динамическую структуру – бинарное дерево. Выбрать все записи о невостребованных учебниках. Методические указания к выполнению задания 2 При выполнении задания для организации поиска необходимой информации использовать рекурсивный обход дерева. Зарание большое спасибо за вашу помощь.
C++ преобразование матрицы http://www.cyberforum.ru/cpp-beginners/thread795223.html
помогите решить.преобразовать заданную матрицу x(p,k) таким образом чтобы первый элемент каждого столбца был заменен произведением последующих элементов того же столбца:help:
C++ Определить месторасположение точки по отношению к кругу Задан круг с центром в точке О(x0,y0) и радиусом R0 и точка А(x1,y1).Определить месторасположение точки по отношению к кругу(находится внутри круга,вне его или лежит на окружности). Добавлено через 14 минут Через cin и cout пожалуста. подробнее

Показать сообщение отдельно
Ildjarn
0 / 0 / 0
Регистрация: 22.02.2013
Сообщений: 9
26.02.2013, 15:25     Перегрузка двойного индексного оператора
Делаю задачу из одной книги. Нужно создать класс DoubleSubscriptedArray.Как видно из названия, класс должен работать с двумерными массивами. Он включает несколько задач, связанных с перегрузкой операторов, но это не столь важно. Реализация всего этого не вызывает у меня затруднений, тем более, что в предшествующем разделе книги есть аналогичный пример для одномерного массива
Но в отличие от примера, новый класс должен работать с двумерными массивами, и обращение к элементам массива
должно производиться посредством перегруженного оператора (), в такой форме:

DoubleSubscriptedArray( row, column )

вместо:

DoubleSubscriptedArray[ row ] [ column ]

Так вот, с реализацией варианта с оператором () все понятно.
Гораздо интереснее реализовать обращение в стандартном формате [ ] [ ].
Но при потпытках это провернуть, возник вопрос: "Возможно ли это вообще сделать?".
Сам двумерный массив у меня реализуется при помощи массива указателей:

C++
1
int **ptr;
А вот мой конструктор:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DoubleSubscriptedArray::DoubleSubscriptedArray( int arrayRow, int arrayColumn )
{    
   if( arrayRow > 0) 
   {
      row = arrayRow;
      column = arrayColumn;
   }
   else
      throw invalid_argument( "Number of columns must be greater than 0" );
      
   ptr = new int*[ arrayRow ];
   
   for( int i = 0; i < arrayRow; ++i )
      ptr[ i ] = new int[ arrayColumn ];
      
   for( int a = 0; a < arrayRow; ++a ) {
      for( int b = 0; b < arrayColumn; ++b )
         ptr[ a ][ b ] = 0;
   }
}
В результате, к элементам массива можно обращаться в формате ptr[ row ][ column ].
Теперь нужно сделать так, чтобы к элементам объекта класса можно было обращаться в таком-же формате.
Надо перегружать оператор [ ]. Появляется вопрос: "Как он вообще работает?".

The result of a subscript expression e1[ e2 ] is given by: *( (e2) + (e1) )
Все понятно - адрес первого элемента + смещение, в конце разыменование. Кроме того, оператор [ ] принимает только один элемент. В случае с multiple subscripts, все происходит так-же:

expression1 [expression2] [expression3]...
Subscript expressions associate from left to right. The leftmost subscript expression, expression1[expression2], is evaluated first. The address that results from adding expression1 and expression2 forms a pointer expression; then expression3 is added to this pointer expression to form a new pointer expression, and so on until the last subscript expression has been added. The indirection operator (*) is applied after the last subscripted expression is evaluated, unless the final pointer value addresses an array type.
То есть, получается, e1[ e3 ][ e2 ] должно быть: *( (e3) + (e2) + (e1) ).
С моим массивом указателей происходит немного по-другому. Если, к примеру, ptr[ 1 ][ 2 ], происходит вот такое:

*( *( ptr + 1 ) + 2 )

Насколько я понимаю, ptr содержит адрес элемента матрицы [ 0 ][ 0 ]. К нему прибавляем значение смещения x, и получаем адрес указателя на элемент [ x ] [ 0 ]. Разыменовываем, получаем сам указатель на элемент [ x ] [ 0 ], к нему прибавляем второе смещение y и получаем адрес элемента матрицы [ x ] [ y ], разыменовываем его, и получаем уже само значение элемента в формате int. Как-то так, насколько я смог разобраться. Это работает.
Дальше "самое простое" - перегрузить соответствующим образом оператор [ ]. Для одномерного массива все просто как доска:

int &Array::operator[]( int subscript )
{
if( subscript < 0 || subscript >= size )
throw out_of_range( "Subscript out of range" );

return *(ptr + subscript );
}

Возвращаем уже готовый, разыменованный указатель, значение int, lvalue. Здесь не массив указателей, просто указатель *ptr.
С двумерным так сделать не получится. Во-первых, оператор [] принимает только один параметр. Значит, передать туда адреса двух смещений сразу не получится. Надо как-то разделять, что-то запоминать. К примеру, ptr[ 1 ][ 2 ], при первом вызове вычислит ptr[ 1 ], запомнит его, а при втором вызове прибавит [ 2 ], и возвратит результат. Все бы хорошо, но тип возвращаемого значения, как не крути, должен оказаться в конце int &. Получается, что при первом вызове возвращается значение типа int, а дальше попытка вычислить выражение типа int[int], что приводит к ошибке:

invalid types `int[int]' for array subscript

То есть, каскадирование не работает. И ничего придумать не получится. Изменить тип возвращаемого значения на какой-нибудь DoubleSubscriptedArray &? Но в конце-концов все равно должен быть int &, то есть значение элемента по заданному адресу, а не объект. Да и как вообще это все будет работать.
То есть, получается, это невозможно реализовать? Как тогда [][] работает со стандартными массивами? Вероятно, так как в англоязычном примере, приводимом мной выше. Во время написания поста у меня появилась мысль, на счет неправильности использования массива указателей, но какая альтернатива?
Буду очень благодарен за любую помощь. Не знаю, насколько понятно удалось это все описать, надеюсь что достаточно подробно.
Да, и еще: я не совсем уверен, что это тема для новичков. Прав создания тем в разделе для экспертов у меня нету. Возможно, модератор согласился-бы перенести эту тему туда? Мне кажется, там ей место.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
 
Текущее время: 17:00. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru