При реализации операции индексирования мы тоже не можем обработать неправильный параметр таким образом, чтобы сообщить клиентской программе об ошибке. В данном случае, в отличие от ситуации с классом TString (см. главу 4), у нас нет специального значения, которое можно было бы возвращать в качестве результата. Единственный вариант обработки ошибки в данном случае — завершать программу аварийно, что и показано в листинге 5.7.
Листинг 5.7. Перегрузка операции индексирования с аварийным завершением
double& TArray::operator[](Uint index) { if (index<size_array) return datafindex]; else { cout << "Index out of range!"; abort(); }
}
const double& TArray::operator[](Uint index) const { if (index<size_array) return data[index]; else { cout << "Index out of range!"; abortQ; }
}
Нам опять требуются две функции, так как при отсутствии второй мы не сможем работать с константными параметрами. Например:
TArray operator*(const TArray &a, const TArray &b);
Попытаемся написать в этой дружественной функции умножения массивов выражение поэлементного умножения:
result[i] = a[i] * b[i];
В этом случае в системе Visual C++.NET дважды выдается ошибка трансляции С2678:
binary '[• : no operator found which takes a left-hand operand of type 'const TArray' (or there is no acceptable conversion)
Система жалуется именно на выражение а [ i ] *b [ i ], так как а и b указаны в заголовке функции как константные массивы.
Вообще-то говоря, для индексирования мы можем использовать любую бинарную операцию, например | (битовая операция ИЛИ), однако этого не следует делать. Программист, который попытается использовать наш умный массив, будет часто ошибаться, так как общепринятый смысл и реализация в С++ этой операции — совсем не индексирование. В С++ есть другая операция, которая очень хорошо подходит для реализации доступа к элементам — это операция вызова функции (). Фактически в листинге 5.7 надо только заменить одни скобки другими (листинг 5.8).
Листинг 5.8. Перегрузка операции () для индексирования
double& ТАггау::operator()(Uint index) { if (index<size_array) return data[index]; else { cout << "Index out of range!"; abort(); }
}
const double& ТАггау::operator()(Uint index) const { if (index<size_array) return data[index]; else { cout << "Index out of range!"; abort(); }
}
Тогда обращение к элементам массива будет выглядеть так: result(i) = a(i) * b(i);
Для С++ это несколько необычная запись, однако в языках Фортран и Бейсик, например, индексы пишутся именно в круглых скобках.
Нужно еще сказать, что применение операции () для индексирования одномерного массива не дает никаких преимуществ по сравнению с обычной операцией [ ]. А вот для индексирования многомерных массивов как раз удобнее использовать круглые скобки. Дело в том, что операция [ ] — бинарная, поэтому в скобках может быть только один операнд-индекс. Это создает некоторые чисто технические неудобства при индексировании многомерных массивов. Поэтому проще задействовать операцию (), так как количество ее аргументов может быть произвольным. Мы еще вернемся к вопросам перегрузки операции (). |