На этом шаге мы рассмотрим назначение и использование указателя this.
Когда функция, принадлежащая классу, вызывается для обработки данных конкретного объекта, этой функции автоматически и неявно передается указатель на тот объект, для которого функция вызвана. Этот указатель имеет фиксированное имя this и незаметно для программиста определен в каждой функции класса следующим образом:
имя_класса::имя_компонентной_функции
имя_класса * const this = адрес_обрабатываемого_объекта;
Имя this является служебным (ключевым) словом. Явно описать или определить указатель this нельзя. В соответствии с неявным определением this является константным указателем, т.е. изменять его нельзя, однако в каждой принадлежащей классу функции он указывает именно на тот объект, для которого функция вызывается. Говорят, что указатель this является дополнительным (скрытым) параметром каждой нестатической компонентной функции. Другими словами, при входе в тело принадлежащей классу функции указатель this инициализируется значением адреса того объекта, для которого вызвана функция. Объект, который адресуется указателем this, становится доступным внутри принадлежащей классу функции именно с помощью указателя this. При работе с компонентами класса внутри принадлежащей классу функции можно было бы везде использовать этот указатель. Например, совершенно правильным будет такое определение класса:
struct ss { int si; char sc; ss(int in, char en) // Конструктор объектов класса. { this->si = in; this->sc = en; } void print(void) // Функция вывода сведений об объекте. { cout << "\n si = " << this->si; cout << "\n sc = " << this->se; } };
В таком использовании указателя this нет никаких преимуществ, так как данные конкретных объектов доступны в принадлежащих классу функциях и с помощью имен данных класса. Однако в некоторых случаях указатель this полезен, а иногда просто незаменим. В следующем примере указатель this позволяет компилятору разобраться в ситуации, когда имя Meaning компонента класса совпадает с именем формального параметра принадлежащей классу функции:
//OOР11_1.СРР - указатель "this". #include <iostream.h> class cell // Класс "числовой элемент". { int static Amount; // Общее количество элементов. int Number; // Порядковый номер элемента. double Meaning; // Значение элемента. public: //Конструктор: cell(double Meaning = 0.0) { // Меняем значение статического компонента: Amount++; this -> Number = Amount; // Компонент и одноименный параметр: this -> Meaning = Meaning; } // Вывод сведений об объекте и количестве элементов: void display (void) { // Лишние this: cout << "\nNumber = " << this->Number; cout << " Amount = " << this->Amount; cout << " Meaning = " << this->Meaning; } }; // Инициализация статического компонента: int cell::Amount = 0; void main(void) { cell A; // Объект с умалчиваемым значением. A.display(); cell B(200.0); cell C(300.0); B.display(); C.display(); }
Результат выполнения программы:
Number = 1 Amount = 1 Meaning = 0 Number = 2 Amount = 3 Meaning = 200 Number = 3 Amount = 3 Meaning = 300
Снятие неоднозначности в теле принадлежащей классу функции между одинаковыми именами формального параметра и компонента класса можно осуществить и без использования указателя this. Гораздо чаще для этой цели применяют операцию изменения видимости, т.е. используют выражение
имя_класса::имя_компонента .
В приведенном примере класса cell конструктор может быть и таким:
cell(double Meaning = 0.0) { Amount++; Number = Amount; cell::Meaning = Meaning; // Устранение неоднозначности. }
На следующем шаге мы продолжим изучение указателя this.