Функции класса, которые объявлены с константным (const) указателем this и непостоянным (volatile) указателем this
Содержание
- 1. Как выглядит общая форма объявления функции с константным указателем this?
- 2. В чем состоит суть объявления функции с константным указателем this?
- 3. Пример, который демонстрирует отличие между функциями с константным указателем this и без него
- 4. Каким образом модифицируется указатель this, который передается функции-члену, которая объявлена с константным указателем this?
- 5. Для чего нужно использовать функции класса с константным указателем this?
- 6. Что будет, если ключевое слово const разместить перед именем функции, а не перед телом функции?
- 7. Можно ли объявлять ключевое слово const для статических функций-членов?
- 8. Какая общая форма объявления функции-члена с непостоянным указателем this? Ключевое слово volatile
- 9. В каких случаях целесообразно объявлять функцию с непостоянным (volatile) указателем this?
- 10. Что дает использование ключевого слова volatile для функции-члена класса?
- 11. Пример использования функций-членов класса с непостоянным указателем this
- Связанные темы
Поиск на других ресурсах:
1. Как выглядит общая форма объявления функции с константным указателем this?
Объявление функции в классе (на примере функций MyFun1(), MyFun2()) с константным указателем this имеет следующий общий вид:
class CMyClass { private: // скрытые члены данных и методы класса // ... public: // функция объявлена с константным указателем this return_type MyFun1(parameters) const; // out-of-line return_type MyFun2(parameters) const // inline реализация { // тело функции // ... } } // реализация out-of-line функции return_type CMyClass::MyFun1(parameters) const { // тело функции MyFun1() // ... }
где
- return_type – тип, который возвращается той или иной функцией;
- parameters – параметры, которые получает функция.
В вышеприведенном фрагменте, в классе CMyClass объявляются две функции с константным указателем this. Функция MyFun1() реализована за пределами класса (типа out-of-line). Функция MyFun2() реализована в классе (типа inline). Перед телом каждой функции стоит ключевое слово const.
2. В чем состоит суть объявления функции с константным указателем this?
В функции с константным указателем this перед телом функции помещается ключевое слово const. Это означает, что тело функции имеет ограниченные возможности использования.
Следует заметить, что в этом случае ключевое слово const не имеет отношение к значению, которое возвращается функцией. Оно имеет значение только для указателя this, используемого в функции.
Если функция объявлена с константным указателем this, то в теле функции запрещается изменять данные класса. При попытке изменить данные класса, будет возникать ошибка компиляции.
3. Пример, который демонстрирует отличие между функциями с константным указателем this и без него
Отличие между обычной функцией и функцией с константным указателем this хорошо видно в реализации нижеследующего класса.
Пусть задан класс CRadius, реализующий радиус некоторого объекта или геометрической фигуры. В классе реализованы:
- внутренний член данных radius типа double;
- конструктор CRadius();
- обычную функцию GetRadius(), которая увеличивает радиус вдвое и возвращает его значение;
- функцию GetRadius2(), объявленную с константным указателем this. Данная функция возвращает значение внутренней переменной radius.
// класс CRadius class CRadius { double radius; public: CRadius(void); // конструктор класса по умолчанию // Обычная функция-член класса, // этой функции неявно передается указатель: CRadius * const this double GetRadius(void) { radius *= 2.0; // разрешено return radius; } // Функция-член класса, объявленная с const // этой функции передается указатель: const CRadius * const this double GetRadius2(void) const { //radius = 2.0; // Запрещено! Ошибка компиляции return radius; } };
Если в функции GetRadius2() попробовать изменить значение внутренней переменной radius, то выйдет ошибка компиляции:
Error: 'radius' cannot be modified because it is being accessed through a const object
Ключевое слово const перед телом функции в классе означает, что функции запрещается вносить любые изменения в члены данных класса.
Использование класса CRadius в некотором программном коде, например, обработчике события:
CRadius CR; double d; d = CR.GetRadius2(); // d = 1.0 - вызов функции с константным this d = CR.GetRadius(); // d = 1.0 - вызов обычной функции-члена
4. Каким образом модифицируется указатель this, который передается функции-члену, которая объявлена с константным указателем this?
Пусть задан класс CRadius, в котором есть функция-член с константным указателем this:
// класс CRadius class CRadius { double radius; public: CRadius(void); // конструктор класса по умолчанию // Обычная функция-член класса, // этой функции неявно передается указатель: CRadius * const this double GetRadius(void) { radius *= 2.0; // разрешено return radius; } // Функция-член класса, объявленная с const // этой функции передается указатель: const CRadius * const this double GetRadius2(void) const { //radius = 2.0; // Запрещено! Ошибка компиляции return radius; } };
Указатель this в классе есть невидимым, для функций класса он передается неявно. Это означает, что при попытке явного описания указателя this в классе, компилятор выдаст ошибку.
Обычной функции-члену класса GetRadius() указатель this передается в неявном виде как:
CRadius * const this;
Функции-члену GetRadius2() невидимый указатель this передается с ключевым словом const:
// модифицированный указатель this const CRadius * const this;
Запись
const CRadius
означает, что объект типа CRadius есть константным объектом. И поэтому, изменять значения объекта в теле функции GetRadius2() нельзя. Итак, нельзя изменять значения внутренних членов-данных класса в функции GetRadius2(). Попытка изменить значения внутреннего члена данных radius в теле функции GetRadius2() вызовет ошибку компиляции.
5. Для чего нужно использовать функции класса с константным указателем this?
Функции с константным указателем this целесообразно использовать в случаях, когда нужно, чтобы функция-член базового класса случайно не переопределилась в производных классах. В этом случае константный указатель this служит защитой данных базового класса от случайного их изменения в производных классах.
6. Что будет, если ключевое слово const разместить перед именем функции, а не перед телом функции?
Это есть важно. В этом случае, функция возвращает константное значение. Но изменять внутренние данные класса в теле функции можно.
Ключевое слово const перед именем функции относится к значению, которое возвращается функцией. Ключевое слово const перед телом функции относится к указателю this.
7. Можно ли объявлять ключевое слово const для статических функций-членов?
Объявление статической функции-члена с ключевым словом const не имеет смысла. При вызове статической функции-члена, невидимый указатель this не передается этой функции. При попытке объявления статической функции-члена с константным указателем this компилятор выдаст ошибку
... modifiers not allowed on static members functions
8. Какая общая форма объявления функции-члена с непостоянным указателем this? Ключевое слово volatile
Для того, чтобы объявить функцию-член с непостоянным указателем this используется ключевое слово volatile.
Общая форма объявления функции с непостоянным указателем this в классе имеет приблизительно следующий вид:
class CMyClass { // скрытые члены данных и методы класса // ... public: // общедоступные члены данных и методы класса // функция-член с непостоянным указателем this return_type MyFun1(parameters) volatile; // out-of-line return_type MyFun2(parameters) volatile // inline { // тело функции // ... } } // реализация out-of-line функции return_type CMyClass::MyFun1() volatile { // тело функции MyFun1() // ... }
где
- return_type – тип, который возвращается той или другой функцией;
- parameters – параметры, которые получает функция.
В вышеприведенном фрагменте, в классе CMyClass объявляются две функции с непостоянным (volatile) указателем this. Функция MyFun1() реализована за пределами класса (типа out-of-line). Функция MyFun2() реализована в классе (типа inline). Перед телом каждой функции стоит ключевое слово volatile.
9. В каких случаях целесообразно объявлять функцию с непостоянным (volatile) указателем this?
Объявление функции как volatile целесообразно использовать в случаях, когда нужно обрабатывать объект класса различными процессами, к которым можно отнести:
- обработка объекта процессором;
- обработка с помощью фоновых прикладных программ;
- обработка с помощью программ обработки прерываний.
10. Что дает использование ключевого слова volatile для функции-члена класса?
Функция-член класса, которая объявлена с ключевым словом volatile трактуется компилятором в разных случаях по разному. Для таких функций компилятор отключает некоторые виды оптимизации в зависимости от типа объявленного объекта.
Функции-члены класса, которые объявлены с ключевым словом volatile можно использовать как для автоматических объектов так и для непостоянных (volatile) объектов.
Для константных объектов использование функций с непостоянным указателем запрещено. Опять же, все зависит от настроек и реализации компилятора.
11. Пример использования функций-членов класса с непостоянным указателем this
Пусть дан класс CRadius. В классе реализованы:
- внутренний член-данных radius;
- конструктор CRadius();
- обычная функция-член класса GetRadius();
- две функции-члены класса с непостоянным указателем this: GetRadius2() и SetRadius().
// класс CRadius class CRadius { double radius; public: CRadius(void); // конструктор класса по умолчанию // Обычная функция-член класса, // этой функции неявно передается CRadius * const this double GetRadius(void) { return radius; } // Функция-член класса, объявленная с volatile // этой функции передается volatile CRadius * const this double GetRadius2(void) volatile { return radius; } // Функция-член класса, объявленная с volatile void SetRadius(double r) volatile { radius = r; } };
Использование класса в другом программном коде
CRadius CR1; // автоматический объект volatile CRadius CR2; // непостоянный объект double d; // автоматический объект CR1.SetRadius(5.5); d = CR1.GetRadius2(); // d = 5.5 // непостоянный объект CR2.SetRadius(6.7); d = CR2.GetRadius2(); // d = 6.7
Как видно из программного кода, функции-члены с непостоянным (volatile) указателем this можно использовать для автоматических и непостоянных объектов. В этом случае, компилятор включает различные виды оптимизации в зависимости от типа объекта.