Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 20.1. Возникновение исключительной ситуации
1: #include < iostream.h> 2: 3: const int DefaultSize = 10; 4: 5: class Array 6: { 7: public: 8: // конструкторы 9: Array(int itsSize = DefaultSize); 10: Array(const Array & rhs); 11: ~Array() { delete [] pType; } 12: 13: // операторы 14: Array& operator=(const Array&); 15: int& operator[](int offSet); 16: const int& operator[](int offSet) const; 17: 18: // методы доступа 19: int GetitsSize() const { return itsSize; } 20: 21: // функция-друг 22: friend ostream& operator< < (ostream&, const Array&); 23: 24: class xBoundary { }; // определяем класс исключений 25: private: 26: int *pType; 27: int itsSize; 28: }; 29: 30: 31: Array:: Array(intsize): 32: itsSize(size) 33: { 34: рТуре = new int[size]; 35: for (int i = 0; i< size; i++) 36: pType[i] = 0; 37: } 38: 39: 40: Array& Array:: operator=(const Array & rhs) 41: { 42: if (this == & rhs) 43: return *thts; 44: delete [] pType; 45: itsSize = rhs.GetitsSiza(); 46: pType = new int[itsSize]; 47: for (int i = 0; i< itsSize; i++) 48: pType[i] = rhs[i]; 49: return *this; 50: } 51: 52: Array:: Array(const Array & rhs) 53: { 54: itsSize = rhs.GetitsSize(); 55: pType = new int[itsSize]; 56: for (int i = 0; i< itsSize; i++) 57: pType[i] = rhs[i]; 58: } 59: 60: 61: int& Array:: operator[](int offSet) 62: { 63: int size = GetitsSize(); 64: if (offSet > = 0 & & offSet < GetitsSize()) 65: return pType[offSet]; 66: throw xBoundary(); 67: return pType[0]; // требование компилятора 68: } 69: 70: 71: const int& Array:: operator[](int offSet) const 72: { 73: int mysize = GetitsSize(); 74: if (offSet > = 0 & & offSet < GetitsSize()) 75: return pType[offSet]; 76: throw xBoundary(); 77: return pType[0]; // требование компилятора 78: } 79: 80: ostream& operator< < (ostream& output, const Array& theArray) 81: { 82: for (int i = 0; i< theArray, GetitsSize(); i++) 83: output < < " [" < < i < < " ] " < < theArray[i] < < endl; 84: return output; 85: } 86: 87: int main() 88: { 89: Array intArray(20); 90: try 91: { 92: for (int ] < < 0; j< 100; j++) 93: { 94: intArray[j] = j; 95: cout < < " intArray[" < < j < < " ] okay..." < < endl; 96: } 97: } 98: catch (Array:: xBoundary) 99: { 100: cout < < " Unable to process your input! \n"; 101: } 102: cout < < " Done.\n"; 103: return 0; 104: }
Результат: intArray[0] okay... intArray[1] okay... intArray[2] okay... intArray[3] okay... intArray[4] okay... intArray[5] okay... intArray[6] okay... intArray[7] okay... intArray[8] okay... intArray[9] okay... intArray[10] okay... intArray[11] okay... intArray[12] okay... intArray[13] okay... intArray[14] okay... intArray[15] okay... intArray[16] okay... intArray[17] okay... intArray[18] okay... intArray[19] okay... Unable to process your input! Done.
Анализ: В листинге 20.1 представлен несколько усеченный класс Array, основанный на шаблоне, разработанном на занятии 19. В строке 24 объявляется новый класс xBoundary внутри объявления внешнего класса Array. В этом новом классе ни по каким внешним признакам нельзя узнать класс обработки исключительных ситуаций. Он чрезвычайно прост и не содержит никаких данных и методов. Тем не менее это вполне работоспособный класс. На самом деле было бы неправильно говорить, что он не содержит никаких методов, потому что компилятор автоматически назначает ему стандартный конструктор, деструктор, конструктор-копировщик и оператор присваивания (=), поэтому у него фактически есть четыре метода, но нет данных. Обратите внимание на то, что его объявление внутри класса Array служит только для объединения двух классов. Как описано в главе 15, класс Array не имеет никакого особого доступа к классу xBoundary, да и класс xBoundary не наделен преимущественным доступом к членам класса Array. В строках 61—68 и 71—78 операторы индексирования ([]) замещены таким образом, чтобы предварительно анализировать введенный индекс смещения и, если оно окажется вне допустимого диапазона, обратиться к классу xBoundary для создания исключения. Назначение круглых скобок состоит в том, чтобы отделить обращение к конструктору класса xBoundary от использования константы перечисления. Обратите внимание, что некоторые компиляторы компании Microsoft требуют, чтобы определение функции в любом случае заканчивалось строкой с оператором return, согласующейся по типу с прототипом функции (в данном случае возвращение ссылки на целочисленное значение), несмотря на то что в случае возникновения исключительной ситуации в строке 66 выполнение программы никогда не достигнет строки 67. Этот пример говорит о том, что логические ошибки не чужды даже компании Microsoft! В строке 90 ключевым словом try начинается блок отслеживания исключительных ситуаций, который оканчивается в строке 97. Внутри этого блока в массив, объявленный в строке 89, добавляется 101 целое число. В строке 98 объявлен блок catch для перехвата исключений класса xBoundary. В управляющей программе в строках 87—104 создается блок try, в котором инициализируется каждый член массива. Когда переменная j (строка 92) увеличится до 20, осуществляется доступ к члену, соответствующему смещению 20. Это приводит к невыполнению условия проверки в строке 64, в результате чего замещенный оператор индексирования operator[] генерирует исключение класса xBoundary (строка 66). Управление программой передается к блоку catch в строке 98, и исключение перехватывается или обрабатывается оператором catch в той же строке, которая печатает сообщение об ошибках. Программа доходит до конца блока catch в строке 100.
|