Опубликован: 26.06.2003 | Уровень: для всех | Доступ: свободно
Лекция 13:

Дополнительные возможности классов

< Лекция 12 || Лекция 13: 12 || Лекция 14 >
Аннотация: Рассматриваются дополнительные возможности при определении классов, включая переопределение операций, определение методов inline и задание собственных преобразований типа.

Переопределение операций

Язык Си++ позволяет определять в классах особого вида методы – операции. Они называются операциями потому, что их запись имеет тот же вид, что и запись операции сложения, умножения и т.п. со встроенными типами языка Си++.

Определим две операции в классе String – сравнение на меньше и сложение:

class String
{
public:
     . . .
  String operator+(const String& s) const;
  bool operator<(const String& s) const;
};

Признаком того, что переопределяется операция, служит ключевое слово operator, после которого стоит знак операции . В остальном операция мало чем отличается от обычного метода класса. Теперь в программе можно записать:

String s1, s2;
. . .
s1 + s2

Объект s1 выполнит метод operator с объектом s2 в качестве аргумента.

Результатом операции сложения является объект типа String. Никакой из аргументов операции не изменяется. Описатель const при описании аргумента говорит о том, что s2 не может измениться при выполнении сложения, а описатель const в конце определения операции говорит то же самое об объекте, выполняющем сложение.

Реализация может выглядеть следующим образом:

String
String::operator+(const String& s) const
{
  String result;
  result.length = length + s.length;
  result.str = new char[result.length + 1];
  strcpy(result.str, str);
  strcat(result.str, s.str);
  return result; 
}

При сравнении на меньше мы будем сравнивать строки в лексикографической последовательности. Проще говоря, меньше та строка, которая должна стоять раньше по алфавиту:

bool
String::operator<(const String& s) const
{
  char* cp1 = str;
  char* cp2 = s.str;
  while (true) {
    if (*cp1 < *cp2)
      return true;
    else if (*cp1 > *cp2)
      return false;
    else {
      cp1++;
      cp2++;  
      if (*cp2 == 0)        // конец строки
        return false;
      else if (*cp1 == 0)   // конец строки  
        return true;
    }
  }
}

Как определять операции

Если для класса определяют операции, то обычно определяют достаточно полный их набор, так, чтобы объекты этого класса могли участвовать в полноценных выражениях.

Прежде всего, определим операцию присваивания. Операция присваивания в качестве аргумента использует объект того же класса и копирует значение этого объекта. Однако, в отличие от копирующего конструктора, у объекта уже имеется какое-то свое значение, и его нужно аккуратно уничтожить.

class String
{
public:
// объявление операции присваивания
String& operator=(const String& s);
};
// Реализация присваивания
String&
String::operator=(const String& s)
{
     if (this == &s)
          return *this;
     if (str != 0) {
          delete [] str;
     }
     length = s.length;
     str = new char[length + 1];
     if (str == 0) {
          // обработка ошибок
     }
     strcpy(str, s.str);
     return *this;
}

Обратим внимание на несколько важных особенностей операции присваивания. Во-первых, в качестве результата операции присваивания объект возвращает ссылку на самого себя. Это дает возможность использовать строки в выражениях типа:

s1 = s2 = s3;

Во-вторых, в начале операции проверяется, не равен ли аргумент самому объекту. Таким образом, присваивание s1 = s1 выполняется правильно и быстро.

В-третьих, перед тем как скопировать новое значение, операция присваивания освобождает память, занимаемую старым значением.

Аналогично операции присваивания можно определить операцию   +=.

Набор операций, позволяющий задействовать класс String в различных выражениях, представлен ниже:

class String
{
public:
  String();
  String(const String& s);
  String(const char*);
  String& operator=(const String& s);
  String& operator+=(const String& s);
  bool operator==(const String& s) const;
  bool operator!=(const String& s) const;
  bool operator<(const String& s) const;
  bool operator>(const String& s) const;
  bool operator<=(const String& s) const;
  bool operator>=(const String& s) const;
  String operator+(const String& s) const;
};
< Лекция 12 || Лекция 13: 12 || Лекция 14 >
Андрей Одегов
Андрей Одегов
Можно ли пересдать ошибочно подтвержденный тест?
Елена Шумова
Елена Шумова
По поводу оплаты за сертификат
Анатолий Федоров
Анатолий Федоров
Россия, Москва, Московский государственный университет им. М. В. Ломоносова, 1989
Рустам Новиков
Рустам Новиков
Эстония, Таллин