Возникает вопрос: так всё-таки можно или нельзя обратиться к члену класса, не указывая его объекта? Уж поверьте мне, что нельзя. Просто когда вы обращаетесь к члену класса Student из addCourse( ) , по умолчанию используется тот экземпляр класса, из которого вызвана функция addCourse( ) . Вы ничего не поняли? Вернёмся к примеру.
int main( int nNumberofArgs , char* pszArgs[ ] )
{
Student s ;
s.semesterHours = 10 ;
s.gpa = 3.0 ;
s.addCourse( 3 , 4.0 ) ; /* Вызов функции-члена */
Student t ;
t.semesterHours = 6;
t.gpa = 1.0 ;
t.addCourse( 3 , 1.5 ) ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
_________________
159 стр. Глава 13. Работа с классами
Когда addCourse( ) вызывается для объекта s , все сокращённые имена в теле этой функции считаются членами объекта s . Таким образом, обращение к переменной semesterHours внутри функции s.addCourse( ) в действительности является обращением к переменной s.semesterHours , а обращение к gpa — обращением к s.gpa . В следующей строке функции main( ) , когда addCourse( ) вызывается для объекта t того же класса Student , происходит обращение к членам класса t.semesterHours и t.gpa .

«Объект, для которого вызывается функция-член, называется "текущим", и все имена членов, записанные в сокращённом виде внутри функции-члена, считаются членами текущего объекта. Другими словами, сокращённое обращение к членам класса интерпретируется как обращение к членам текущего объекта.»
[ Помни! ]
Именование текущего объекта...160

«Как функция-член определяет, какой объект является текущим? Это не магия и не шаманство — просто адрес этого объекта всегда передаётся функции-члену как скрытый первый аргумент. Другими словами, при вызове функции-члена происходит преобразование такого вида:
s.addCourse( 3 , 2.5 ) равносильноStudent::addCourse( & s , 3 , 2.5 )
( команда, приведённая в правой части выражения, синтаксически неверна; она просто показывает, как компилятор видит выражение в левой части во внутреннем представлении ).»
[ Технические подробности ]
Внутри функции, когда нужно узнать, какой именно объект является текущим, используется этот указатель. Тип текущего объекта — указатель на объект соответствующего класса. Всякий раз, когда функция-член обращается к другому члену класса, не называя имени его объекта явно, компилятор считает, что данный член является членом этого ( this ) объекта. При желании вы можете явно обращаться к членам этого объекта, используя ключевое слово this . Так что функцию Student::addCourse( ) можно переписать следующим образом:
float Student::addCourse( int hours , float grade )
{
float weightedGPA ;
weightedGPA = this -> semesterHours * this -> gpa ;
/* добавим новый курс */
this -> semesterHours += hours ;
weightedGPA += hours * grade ;
this -> gpa = weightedGPA / this -> semesterHours ;
return this -> gpa ;
}
Независимо от того, добавите ли вы оператор this -> в тело функции явно или нет, результат будет одинаков.
_________________
160 стр. Часть 3. Введение в классы
►Разрешение области видимости...161
Символ :: между именем класса и именем его члена называют оператором разрешения области видимости, поскольку он указывает, какой области видимости принадлежит член класса. Имя класса перед двоеточиями похоже на фамилию, тогда как название функции после двоеточия схоже с именем — такой порядок записи принят на востоке.
С помощью оператора :: можно также описать функцию — не член, использовав для этого пустое имя класса. В этом случае функция addCourse( ) должна быть описана как ::addCourse( int , float ) .
Обычно оператор :: не обязателен, однако в некоторых ситуациях это не так. Рассмотрим следующий фрагмент кода:
/* addCourse — перемножает количество часов и оценку */
float addCourse( int hours , float grade )
{
return hours * grade ;
}
class Student
{
public :
int semesterHours ;
float gpa ;
/* Добавить пройденный курс к записи */
float addCourse( int hours , float grade )
{
/* Вызвать внешнюю функцию */
Читать дальше