Рейтинговые книги
Читем онлайн Освой самостоятельно С++ за 21 день. - Джесс Либерти

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 138 139 140 141 142 143 144 145 146 ... 170

Производные классы объявляют конструктор, который лишь инициализирует базовый класс. При этом никакие другие функции объявлены не были (частично из экономии места в листинге).

Операторы catch в строках 114-136 изменены таким образом, чтобы создавать именованный объект исключения (thoException), который используется в теле блока catch для доступа к данным, сохраняемым в переменной-члене itsSize.

Примечание:При работе с исключениями следует помнить об их сути: если уж оно возникло, значит, что-то не в порядке с распределением ресурсов, и обработку этого исключения нужно записать таким образом, чтобы вновь не создать ту же проблему. Следовательно, если вы создаете исключение OutOfMemory, то не стоит а конструкторе этого класса пытаться выделить память для какого-либо объекта.

Весьма утомительно писать вручную все эти конструкции с операторами oatch, каждый из которых должен выводить свое сообщение. Тем более, что при увеличении объема программы стремительно возрастает вероятность возникновения в ней ошибок. Лучше переложить эту работу на объект исключения, который сам должен определять тип исключения и выбирать соответствующее сообщение. В листинге 20.5 для решения этой проблемы использован подход, который в большей степени отвечает принципам объектно-ориентированного программирования. В классах исключений применяются виртуальные функции, обеспечивающие полиморфизм объекта исключения.

Листинг 20.5. Передача аргументов как ссылок u использование виртуальных функций в классах исключений

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<<

23:         (ostream&, const Array&);

24:

25:      // определение классов исключений

26:      class xBoundary { };

27:      class xSize

28:      {

29:         public:

30:            xSize(int size):itsSize(size) { }

31:            ~xSize(){ }

32:            virtual int GetSize() { return itsSize; }

33:            virtual void PrintError()

34:            {

35:               cout << "Size error. Received: ";

36:               cout << itsSize << endl;

37:            }

38:         protected:

39:            int itsSize;

40:      };

41:

42:      class xTooBig : public xSize

43:      {

44:         public:

45:            xTooBig(int size):xSize(size){ }

46:            virtual void PrintError()

47:            {

48:               cout << "Too big. Received: ";

49:               cout << xSize::itsSize << endl;

50:            }

51:      };

52:

53:      class xTooSmall : public xSize

54:      {

55:         public:

56:            xTooSmall(int size):xSize(size){ }

57:            virtual void PrintError()

58:            {

59:               cout << "Too small. Received: ";

60:               cout << xSize::itsSize << endl;

61:            }

62:      };

63:

64:      class xZero : public xTooSmall

65:      {

66:         public:

67:            xZero(int size):xTooSmall(size){ }

68:            virtual void PrintError()

69:            {

70:               cout << "Zero!. Received: " ;

71:               cout << xSize::itsSize << endl;

72:            }

73:      };

74:

75:      class xNegative : public xSize

76:      {

77:         public:

78:            xNegative(int size):xSize(size){ }

79:            virtual void PrintError()

80:            {

81:               cout << "Negative! Received: ";

82:               cout << xSize::itsSize << endl;

83:            }

84:      };

85:

86:   private:

87:      int *pType;

88:      int itsSize;

89: };

90:

91: Array::Array(int size):

92: itsSize(size)

93: {

94:    if (size == 0)

95:       throw xZero(size);

96:    if (size > 30000)

97:       throw xTooBig(size);

98:    if (size <1)

99:       throw xNegative(size);

100:   if (size < 10)

101:      throw xTooSmall(size);

102:

103:   pType = new int[size];

104:   for (int i = 0: i<size; i++)

105:      pType[i] = 0;

106: }

107:

108: int& Array::operator[] (int offSet)

109: {

110:    int size = GetitsSize();

111:    if (offSet >= 0 && offSet < GetitsSize())

112:       return pType[offSet];

113:    throw xBoundary();

114:    return pType[0];

115: }

116:

117: const int& Array::operator[] (int offSet) const

118: {

119:    int size = GetitsSize();

120:    if (offSet >= 0 && offSet < GetitsSize())

121:       return pType[offSet];

122:    throw xBoundary();

123:    return pType[0];

124: }

125:

126: int main()

127: {

128:

129:    try

130:    {

131:       Array intArray(9);

132:       for (int j = 0: j< 100; j++)

133:       {

134:          intArray[j] - j;

135:          cout << "intArray[" << j << "] okay...n";

136:       }

137:    }

138:    catch (Array::xBoundary)

139:    {

140:       cout << "Unable to process your input!n";

141:    }

142:    catch (Array;:xSize& theExoeption)

143:    {

144:       theException.PrintError();

145:    }

146:    catch (...)

147:    {

148:       cout << "Something went wrong!n";

149:    }

150:    cout << "Done.n";

151:    return 0;

152: }

Результат:

Too small! Received: 9

Done.

Анализ: В листинге 20.5 показано объявление виртуального метода PrintError() в классе xSize, который выводит сообщения об ошибках и истинный размер класса. Этот метод замешается в каждом производном классе исключения.

В строке 142 объявляется объект исключения, который является ссылкой. При вызове функции PrintError() со ссылкой на объект благодаря полиморфизму вызывается нужная версия функции PrintError(). В результате программный код становится яснее, проще для понимания, а следовательно, и для дальнейшей поддержки.

Исключения и шаблоны

При создании исключений, предназначенных для работы с шаблонами, есть два варианта решений. Можно создавать исключение прямо в шаблоне, и тогда они будут доступны для каждого экземпляра шаблона, а можно использовать классы исключений, созданные вне объявления шаблона. Оба этих подхода показаны в листинге 20.6.

Листинг 20.6. Использование исключений с шаблонами

1: #include <iostream.h>

2:

3: const int DefaultSize = 10;

4: class xBoundary { } ;

5:

6: template <class T>

7: class Array

8: {

9:    public:

10:      // конструкторы

11:      Array(int itsSize = DefaultSize);

12:      Array(const Array &rhs);

13:      ~Array() { delete [] pType;}

14:

15:      // операторы

16:      Array& operator=(const Array<T>&);

17:      T& operator[](int offSet);

18:      const T& operator[](int offSet) const;

19:

20:      // методы доступа

21:      int GetitsSize() const { return itsSize; }

22:

23:      // функция-друг

24:      friend ostream& operator<< (ostream&, const Array<T>&);

25:

26:      // определение классов исключений

27:

28:      class xSize { };

29:

30:   private:

31:      int *pType;

32:      int itsSize;

33: };

34:

35: template <class T>

36: Array<T>::Array(int size):

37: itsSize(size)

38: {

39:    if (size <10 || size > 30000)

40:       throw xSize();

41:    рТуре = new T[size];

42:    for (int i = 0; i<size; i++)

43:       pType[i] = 0;

44: }

45:

46: template <class T>

47: Array<T>& Array<T>::operator=(const Array<T> &rhs)

48: {

49:    if (this == &rhs)

50:       return *this;

51:    delete [] рТуре;

52:    itsSize = rhs.GetitsSize();

53:    рТуре = new T[itsSize];

54:    for (int i = 0; i<itsSize; i++)

55:       pType[i] = rhs[i];

56: }

57: template <class T>

58: Array<T>::Array(const Array<T> &rhs)

59: {

60:    itsSize = rhs.GetitsSize();

61:    рТуре = new T[itsSize];

62:    for (int i = 0; i<itsSize; i++)

63:       pType[i] = rhs[i];

64: }

65:

66: template <class T>

67: T& Array<T>::operator[](int offSet)

68: {

69:    int size = GetitsSize();

70:    if (offSet >= 0 && offSet < GetitsSize())

71:       return pType[offSet];

72:    throw xBoundary():

73:    return pType[0];

74: }

75:

76: template <class T>

77: const T& Array<T>::operator[](int offSet) const

78: {

79:    int mysize = GetitsSize();

80:    if (offSet >= 0 && offSet < GetitsSize())

81:       return pType[offSet];

82:    throw xBoundary();

83: }

84:

85: template <class T>

86: ostream& operator<< (ostream& output, const Array<T>& theArray)

87: {

88:    for (int i = 0; i<theArray,GetitsSize(); i++)

89:       output << "[" << i << "] " << theArray[i] << endl;

90:    return output;

91: }

92:

93:

94: int main()

95: {

96:

97:    try

98:    {

99:       Array<int> intArray(9);

100:      for (int j = 0; j< 100; j++)

101:      {

102:         intArray[j] = j;

103:         cout << "intArray[" << j << "] okay..." << endl;

1 ... 138 139 140 141 142 143 144 145 146 ... 170
На этой странице вы можете бесплатно читать книгу Освой самостоятельно С++ за 21 день. - Джесс Либерти бесплатно.

Оставить комментарий