ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 6) онлайн

Константные методы

Константные методы отличаются тем, что не изменяют значений полей своего класса. Рассмотрим это на примере под названием CONSTFU:

// constfu.cpp

// применение константных методов

class aClass

{

private:

  int alpha; public:

  void nonFunc()              // неконстантный метод

    { alpha = 99; }                  // корректно

  void conFunc()const   // константный метод     { alpha = 99; }                // ошибка: нельзя изменить значение поля

};

 

Обычный метод nonFunc() может изменить значение поля alpha, а констант- ный метод conFunc() не может. Если со стороны последнего будет предпринята попытка изменить поле alpha, компилятор выдаст сообщение об ошибке.

Для того чтобы сделать функцию константной, необходимо указать ключевое слово const после прототипа функции, но до начала тела функции. Если объяв- ление и определение функции разделены, то модификатор const необходимо указывать дважды — как при объявлении функции, так и при ее определении. Те методы, которые лишь считывают данные из поля класса, имеет смысл де- лать константными, поскольку у них нет необходимости изменять значения по- лей объектов класса.

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

Пример класса Distance

Для того чтобы не включать множество нововведений в одну программу, мы до сих пор не использовали в наших примерах константные методы. Однако суще- ствует немалое количество ситуаций, где применение константных методов было бы весьма полезным. Например, метод showdist() класса Distance, неоднократно фигурировавшего в наших примерах, следовало сделать константным, потому что он не изменяет (и не должен изменять!) полей того объекта, для которого он вызывается. Он предназначен лишь для вывода текущих значений полей на экран.

Аналогично, метод add_dist() программы ENGLRET не должен изменять данных, хранящихся в объекте, из которого он вызывается. Значение этого объекта долж- но складываться с тем значением, которое метод принимает в качестве аргумента, а полученный результат возвращается вызывающей программе. Мы внесли изме-

нения в программу ENGLRET, сделав два указанных метода константными. Обра- тите внимание на то, что модификаторы const появились как в объявлениях, так и в определениях методов.

// engConst.cpp

// константные методы и константные аргументы

#include <iostream>

using namespace std;

//////////////////////////////////////////////////////////

class Distance                  // длина в английской системе

{

  private:

    int feet;

    float inches;

  public:                       // конструктор без аргументов

    Distance() : feet(0), inches(0.0)

      { }                       // конструктор с двумя аргументами

    Distance(int ft, float in) : feet(ft), inches(in)

      { }

    void getdist()              // ввод длины пользователем

    {

      cout << "\nВведите число футов: "; cin >> feet;

      cout << "Введите число дюймов: "; cin >> inches;

    }

    void showdist()const        // вывод длины

      { cout << feet << "\'-" << inches <<'\"'; }

    Distance add_dist(const Distance&) const; // сложение

};

//--------------------------------------------------------

// сложение данного объекта с d2, возврат суммы

Distance Distance::add_dist(const Distance& d2) const

{

  Distance temp;                // временная переменная

  // feet = 0;                  // Ошибка: нельзя изменить поле

  // d2.feet = 0;               // Ошибка: нельзя изменить d2

  temp.inches = inches + d2.inches; // сложение дюймов

  if( temp.inches >= 12.0 )     // если сумма превышает 12.0,

  {                             // то уменьшаем ее на 12.0

    temp.inches -= 12.0;        // и увеличиваем число футов

    temp.feet = 1;              // на 1

  }

  temp.feet += feet + d2.feet;  // сложение футов

  return temp;

}

//////////////////////////////////////////////////////////

int main()

{

  Distance dist1, dist3;        // две длины

  Distance dist2(11, 6.25);     // определение и инициализация dist2

  dist1.getdist();              // ввод dist1

  dist3 = dist1.add_dist(dist2);//dist3 = dist1 + dist2

  // вывод всех длин

  cout << "\ndist1 = "; dist1.showdist();

  cout << "\ndist2 = "; dist2.showdist();

  cout << "\ndist3 = "; dist3.showdist();

  cout << endl;

  return 0;

}

 

В этом примере обе функции showdist() и add_dist() являются константными. В теле функции add_dist() первый из закомментированных операторов, feet=0, демонстрирует, что компилятор выдаст ошибку при попытке изменения кон- стантной функцией полей объекта, из которого она вызывалась.

Константные аргументы методов

В главе 5 мы говорили о том, что если вы хотите передать аргумент в функцию по ссылке и в то же время защитить его от изменения функцией, необходимо сделать этот аргумент константным при объявлении и определении функции. Методы классов в этом отношении не являются исключениями. В программе ENGCONST мы передаем аргумент в функцию add_dist() по ссылке, но хотим быть уверенными в том, что функция не изменит значения этого аргумента, в качестве которого при вызове выступает переменная dist2 функции main(). Для этого па- раметр d2 функции add_dist() указывается с модификатором const в ее объявле- нии и определении. Второй из закомментированных операторов показывает, что компилятор выдаст ошибку при попытке функции add_dist() изменить значение своего аргумента.

 

27