13.4. Неявный указатель this
У каждого объекта класса есть собственная копия данных-членов. Например:
int main() {
Screen myScreen( 3, 3 ), bufScreen;
myScreen.clear();
myScreen.move( 2, 2 );
myScreen.set( '*' );
myScreen.display();
bufScreen.resize( 5, 5 );
bufScreen.display();
}
У объекта myScreen есть свои члены _width, _height, _cursor и _screen, а у объекта bufScreen – свои. Однако каждая функция-член класса существует в единственном экземпляре. Их и вызывают myScreen и bufScreen.
В предыдущем разделе мы видели, что функция-член может обращаться к членам своего класса, не используя операторы доступа. Так, определение функции move() выглядит следующим образом:
inline void Screen::move( int r, int c )
{
if ( checkRange( r, c ) ) // позиция на экране задана корректно?
{
int row = (r-1) * _width; // смещение строки
_cursor = row + c - 1;
}
}
Если функция move() вызывается для объекта myScreen, то члены _width и _height, к которым внутри нее имеются обращения, – это члены объекта myScreen. Если же она вызывается для объекта bufScreen, то и обращения производятся к членам данного объекта. Каким же образом _cursor, которым манипулирует move(), оказывается членом то myScreen, то bufScreen? Дело в указателе this.
Каждой функции-члену передается указатель на объект, для которого она вызвана, – this. В неконстантной функции-члене это указатель на тип класса, в константной – константный указатель на тот же тип, а в функции со спецификатором volatile указатель с тем же спецификатором. Например, внутри функции-члена move() класса Screen указатель this имеет тип Screen*, а в неконстантной функции-члене List – тип List*.
Поскольку this адресует объект, для которого вызвана функция-член, то при вызове move() для myScreen он указывает на объект myScreen, а при вызове для bufScreen – на объект bufScreen. Таким образом, член _cursor, с которым работает функция move(), в первом случае принадлежит объекту myScreen, а во втором – bufScreen.
Понять все это можно, если представить себе, как компилятор реализует объект this. Для его поддержки необходимо две трансформации:
Изменить определение функции-члена класса, добавив дополнительный параметр:
// псевдокод, показывающий, как происходит расширение
// определения функции-члена
// ЭТО НЕ КОРРЕКТНЫЙ КОД C++
inline void Screen::move( Screen *this, int r, int c )
{
if ( checkRange( r, c ) )
{
int row = (r-1) * this-<_width;
this-<_cursor = row + c - 1;
}
}
В этом определении использование указателя this для доступа к членам _width и _cursor сделано явным.
Изменение каждого вызова функции-члена класса с целью передачи одного дополнительного аргумента – адреса объекта, для которого она вызвана:
myScreen.move( 2, 2 );
транслируется в
move( &myScreen, 2, 2 );
Программист может явно обращаться к указателю this внутри функции. Так, вполне корректно, хотя и излишне, определить функцию-член home() следующим образом:
inline void Screen::home()
{
this->_cursor = 0;
}
Однако бывают случаи, когда без такого обращения не обойтись, как мы видели на примере функции-члена copy() класса Screen. В следующем подразделе мы рассмотрим и другие примеры.
- 11. Базы данных, определение, типы бд. Понятие домена, атрибута,
- 32. История создания эвм. Поколения и классы эвм. Структура
- 46. Общая характеристика операционной системы Linux. Основные
- 67. Понятие нормальной формы отношений. Условия нахождения бд
- 1.3D моделирование в компьютерной графике
- 2. Case-средства. Работа с case-средством Erwin. Логическая и
- 4. Алгоритм декомпозиции отношения с целью его нормализации.
- 7. Архивирование данных. Преимущества и недостатки современных
- 12. Баухауз и его вклад в развитие мирового дизайна.
- 13. Бизнес - цели и жизненный цикл изделия
- 15. Василий Кандинский – теория цвета. Психология цвета.
- 16. Векторная и растровая графика, основные понятия, области
- 18. Виды обеспечения систем компьютерной графики.
- 21. Единый формат векторной графики.
- Пример использования tadoConnection
- Пример использования параметров запроса
- Синхронизация данных клиента и сервера.
- Работа с транзакциями
- Пример работы с транзакциями
- Доступ к данным
- Пример работы с отложенными изменениями.
- Cals-идеология
- Cals-технологии
- Cals-системы
- Плюсы и минусы
- 28. Использование векторной и растровой графики в web.
- 30. Использование международных стандартов.
- 34. Конструктивизм в художественном дизайне.
- 35. Кривая Безье, ее построение и редактирование.
- 13.1. Определение класса
- 13.1.1. Данные-члены
- 13.1.2. Функции-члены
- 13.1.5. Объявление и определение класса
- 13.2. Объекты классов
- 13.4. Неявный указатель this
- 13.4.1. Когда использовать указатель this
- 38. Мастера модерна. А. Ванде Вельде, ч. Р. Макинтош.
- 43. Обеспечение информационной безопасности.
- 44. Области применения компьютерной графики.
- 48. Оптические устройства хранения информации. Виды и основные
- 50. Основные принципы cals.
- 52. Основные структурные элементы эвм (материнские платы,
- Основные характеристики шрифтов
- Художественный облик шрифтов
- 55. Основы композиции в промышленном дизайне. Категории
- Оператор break
- Оператор return
- 60. П. Беренс – первый промышленный дизайнер.
- 61. Параллельное и последовательное моделирование
- 62. Параметризация в компьютерной графике.
- 63. Первые теории дизайна Дж. Рескин, г. Земпер, ф. Рело.
- 65. Понятие ключа, первичного ключа, индекса.
- Первая нормальная форма (1nf)
- Вторая нормальная форма (2nf)
- Третья нормальная форма (3nf)
- Методы решения
- Процедура принятия решений
- 4. Отчеты - позволяют обобщать и распечатывать информацию. Создание базы данных
- Создание формы
- Вызовы sql в pl/sql-ном блоке
- Вызовы sql в pl/sql-ном блоке
- См. Вопрос 122 fat32. Чем она лучше fat16?
- Оттенки фиолетового
- Оттенки синего
- Оттенки зеленого
- Оттенки желтого
- Цветовая гармония
- Восприятие цвета
- Различие между цветами Различные источники света
- Различная ориентация
- Различия в восприятии размера