Помните, что класс сам является областью видимости (см. раздел 2.6.1). Определения функций-членов класса находятся в области видимости самого класса. Следовательно, использованное функцией isbn()
имя bookNo
относится к переменной-члену, определенной в классе Sales_data
.
Следует заметить, что функция isbn()
может использовать имя bookNo
, несмотря на то, что оно определено isbn()
. Как будет описано в разделе 7.4.1, компилятор обрабатывает классы в два этапа — сначала объявления членов класса, затем тела функций-членов, если таковые вообще имеются. Таким образом, тела функций-членов могут использовать другие члены своих классов, независимо от того, где именно в классе они определены.
Подобно любой другой функции, при определении функции-члена вне тела класса ее определение должно соответствовать объявлению. Таким образом, тип возвращаемого значения, список параметров и имя должны совпадать с объявлением в теле класса. Если член класса был объявлен как константная функция, то в определении после списка параметров также должно присутствовать ключевое слово const
. Имя функции-члена, определенное вне класса, должно включить имя класса, которому она принадлежит:
double Sales_data::avg_price() const {
if (units_sold)
return revenue/units_sold;
else
return 0;
}
Имя функции, Sales data::avg_price()
, использует оператор области видимости (см. раздел 1.2), чтобы указать, что определяемая функция по имени avg_price
объявлена в пределах класса Sales_data
. Как только компилятор увидит имя функции, остальная часть кода интерпретируется как относящаяся к области видимости класса. Таким образом, когда функция avg_price()
обращается к переменным revenue
и units_sold
, она неявно имеет в виду члены класса Sales_data
.
this
на объектФункция combine()
должна действовать как составной оператор присвоения +=
. Объект, для которого вызвана эта функция, представляет собой левый операнд присвоения. Правый операнд передается как аргумент явно:
Sales_data& Sales_data::combine(const Sales_data &rhs) {
units_sold += rhs.units_sold; //
revenue += rhs.revenue; //
return *this; //
}
Когда наша программа обработки транзакций осуществляет вызов
total.combine(trans); //
адрес объекта total
находится в неявном параметре this
, а объект trans
связан с параметром rhs
. Таким образом, при вызове функции combine()
выполняется следующий оператор:
units_sold += rhs.units_sold; //
В результате произойдет сложение переменных total.units_sold
и trans.units_sold
, а сумма должна сохраниться снова в переменной total.units_sold
.
Самым интересным в этой функции является тип возвращаемого значения и оператор return
. Обычно при определении функции, работающей как стандартный оператор, она должна подражать поведению этого оператора. Стандартные операторы присвоения возвращают свой левый операнд как l-значение (см. раздел 144). Чтобы возвратить l-значение, наша функция combine()
должна возвратить ссылку (см. раздел 6.3.2). Поскольку левый операнд — объект класса Sales_data
, тип возвращаемого значения — Sales_data&
.
Как уже упоминалось, для доступа к члену объекта, функция-член которого выполняется, необязательно использовать неявный указатель this
. Однако для доступа к объекту в целом указатель this
действительно нужен:
return *this; //
Здесь оператор return обращается к значению указателя this
, чтобы получить объект, функция которого выполняется. Таким образом, для этого вызова возвращается ссылка на объект total
.
Упражнение 7.2. Добавьте функции-члены combine()
и isbn()
в класс Sales_data
, который был написан для упражнений из раздела 2.6.2.
Упражнение 7.3. Пересмотрите свою программу обработки транзакций из раздела 7.1.1 так, чтобы использовать эти функции-члены.
Упражнение 7.4. Напишите класс по имени Person
, представляющий имя и адрес человека. Используйте для содержания каждого из этих членов тип string
. В последующих упражнениях в этот класс будут добавлены новые средства.