Введение в язык Си++

Функции Члены


Рассмотрим реализацию понятия даты с использованием struct для того, чтобы определить представление даты date и множества функций для работы с переменными этого типа:

struct date { int month, day, year; }; // дата: месяц, день, год } date today; void set_date(date*, int, int, int); void next_date(date*); void print_date(date*); // ...

Никакой явной связи между функциями и типом данных нет. Такую связь можно установить, описав функции как члены:

struct date { int month, day, year;

void set(int, int, int); void get(int*, int*, int*); void next(); void print(); };

Функции, описанные таким образом, называются функциями членами и могут вызываться только для специальной переменной соответствующего типа с использованием стандартного синтаксиса для доступа к членам структуры. Например:

date today; // сегодня date my_burthday; // мой день рождения

void f() { my_burthday.set(30,12,1950); today.set(18,1,1985);

my_burthday.print(); today.next(); }

Поскольку разные структуры могут иметь функции члены с одинаковыми именами, при определении функции члена необходимо указывать имя структуры:

void date::next() { if ( ++day 28 ) { // делает сложную часть работы } }

В функции члене имена членов могут использоваться без явной ссылки на объект. В этом случае имя относится к члену того объекта, для которого функция была вызвана.




Просто структуры данных вроде employee и manager на самом деле не столь интересны и часто не особенно полезны, поэтому рассмотрим, как добавить к ним функции. Например:

class employee { char* name; // ... public: employee* next; void print(); // ... };

class manager : public employee { // ... public: void print(); // ... };

Надо ответить на некоторые вопросы. Как может функция член производного класса manager использовать члены его базового класса employee? Как члены базового класса employee могут использовать функции члены производного класса manager? Какие члены базового класса employee может использовать функция не член на объекте типа manager? Каким образом программист может повлиять на ответы на эти вопросы, чтобы удовлетворить требованиям приложения?

Рассмотрим:

void manager::print() { cout

Член производного класса может использовать открытое имя из своего базового класса так же, как это могут делать другие члены последнего, то есть без указания объекта. Предполагается, что на объект указывает this, поэтому (корректной) ссылкой на имя name является this-name. Однако функция manager::print компилироваться не будет, член производного класса не имеет никакого особого права доступа к закрытым членам его базового класса, поэтому для нее name недоступно.

Это многим покажется удивительным, но представьте себе другой вариант: что функция член могла бы обращаться к закрытым членам своего базового класса. Возможность, позволяющая программисту получать доступ к закрытой части класса просто с помощью вывода из него другого класса, лишила бы понятие закрытого члена всякого смысла. Более того, нельзя было бы узнать все использования закрытого имени посмотрев на функции, описанные как члены и друзья этого класса. Пришлось бы проверять каждый исходный файл во всей программе на наличие в нем производных классов, потом исследовать каждую функцию этих классов, потом искать все классы, производные от этих классов, и т.д. Это по меньшей мере утомительно и скорее всего нереально.




Функция, описанная как член, (без спецификатора friend (#8.5.9)) называется функцией членом и вызывается с помощью синтаксиса члена класса (#7.1). Например:

struct tnode { char tword[20]; int count; tnode *left; tnode *right; void set (char* w,tnode* l,tnode* r); };

tnode n1, n2;

n1.set ("asdf",n2,0); n2.set ("ghjk",0,0);

Определение функции члена рассматривается как находящееся в области видимости ее класса. Это значит, что она может непосредственно использовать имена ее класса. Если определение функции члена находится вне описания класса, то имя функции члена должно быть уточнено именем класса с помощью записи

typedef-имя . простое_оп_имя

см. 3.3. Определения функций обсуждаются в

).

В члене функции ключевое слово this указывает на объект, для которого вызвана функция. Типом this в функции, которая является членом класса cl, является cl*. Если mem - член класса cl,то mem и this-mem - синонимы в функции члене класса cl (если mem не был использован в качестве имени локальной переменной в промежуточной области видимости).

Функция член может быть определена (#10.1) в описании класса. Помещение определения функции члена в описание класса является кратким видом записи описания ее в описании класса и затем определения ее как inline () сразу после описания класса. Например:

int b; struct x { int f () { return b; } int f () { return b; } int b; };

означает

int b; struct x { int f (); int b; }; inline x.f () { return b; }

Для функций членов не нужно использование спецификатора overload (): если имя описывается как означающее несколько имен в классе, то оно перегружено (см. #8.9).

Применение операции получения адреса к функциям членам допустимо. Тип параметра результирующей функции указатель на есть (...), то есть, неизвестен (). Любое использование его является зависимым от реализации, поскольку способ инициализации указателя для вызова функции члена не определен.



Содержание раздела