Выбрать главу

        t.semesterHours = 6 ;

        t.gpa = 1.0 ;

        t.addCourse( 3 , 1.5 ) ;

        /* Пауза для того, чтобы посмотреть на результат работы программы */

        system( "PAUSE" ) ; return 0 ;

    } 

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

Факт вызова этой функции можно определить так: "s является объектом, на который действует addCourse( ) " ; или, другими словами, объект s представляет собой студента, к записи которого добавляется новый курс. Вы не можете получить информацию о студенте или изменить её, не указав, о каком конкретно студенте идёт речь.

Вызов функции-члена без указания имени объекта имеет не больше смысла, чем обращение к данным-членам без указания объекта.

Доступ к членам из функции-члена...159

Я так и слышу, как вы повторяете про себя: "Нельзя обратиться к функции-члену без указания имени объекта! Нельзя обратиться к функции-члену без указания имени объекта! Нельзя..." Запомнив это, вы смотрите на тело функции-члена Student::addCourse( ) и... что это? Ведь addCourse( ) обращается к членам класса, не уточняя имени объекта!

Возникает вопрос: так всё-таки можно или нельзя обратиться к члену класса, не указывая его объекта? Уж поверьте мне, что нельзя. Просто когда вы обращаетесь к члену класса 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( ) можно переписать следующим образом: