Язык программирования C++. Вводный курс


Функции-члены со спецификаторами const и volatile - часть 2


 

error: cannot modify a data member within a const member function

ошибка: не могу модифицировать данные-члены внутри константной функции-члена

 

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

#include <cstring>

 

class Text {

public:

   void bad( const string &parm ) const;

private:

   char *_text;

};

 

void Text::bad( const string &parm ) const

{

   _text = parm.c_str();   // ошибка: нельзя модифицировать _text

 

   for ( int ix = 0; ix < parm.size(); ++ix )

       _text[ix] = parm[ix];   // плохой стиль, но не ошибка

}

Модифицировать _text

нельзя, но это объект типа char*, и символы, на которые он указывает, можно изменить внутри константной функции-члена класса Text. Функция-член bad()

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

Константную функцию-член можно перегружать неконстантной функцией с тем же списком параметров:

class Screen {

public:

   char get(int x, int y);

   char get(int x, int y) const;

   // ...

};

В этом случае наличие спецификатора const у объекта класса определяет, какая из двух функций будет вызвана:

int main() {

   const Screen cs;

   Screen s;

 

   char ch = cs.get(0,0);   // вызывает константную функцию-член

   ch = s.get(0,0);         // вызывает неконстантную функцию-член

}

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

трактуется как константный с момента завершения работы конструктора и до вызова деструктора.

Функцию-член можно также объявить со спецификатором volatile (он был введен в разделе 3.13). Объект класса объявляется как volatile, если его значение изменяется способом, который не обнаруживается компилятором (например, если это структура данных, представляющая порт ввода/вывода). Для таких объектов вызываются только функции-члены с тем же спецификатором, конструкторы и деструкторы:

class Screen {

public:

   char poll() volatile;

   // ...

};

char Screen::poll() volatile { ... }




Начало  Назад  Вперед



Книжный магазин