Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
posobie1.doc
Скачиваний:
13
Добавлен:
01.05.2019
Размер:
457.22 Кб
Скачать

3.4. Определение компонентных функций класса

Компонентные функции класса могут быть определены как в теле класса (такой способ использован во всех приведенных примерах), так и за телом класса на внешнем уровне программы. Для методов класса, определенных внутри тела класса, компилятор применяет модификатор inline, то есть объявляет такие методы встраиваемыми (подставляемыми) функциями. Таким образом, на эти функции накладываются ограничения, аналогичные ограничениям для inline-функций (не могут содержать циклов, оператор-переключатель и оператор безусловного перехода, не могут быть рекурсивными и т.д.). Если метод класса определен в теле класса и не удовлетворяет какому-либо из перечисленных условий (например, содержит оператор цикла for), то компилятор транслирует данный метод как обычную, не подставляемую функцию, при этом выводя предупреждение времени компиляции (в BC++ v5.02 «Functions containing for are not expanded inline»). Для компонентных функций, определенных вне тела класса, никаких ограничений не существует, подставляемыми по умолчанию они не объявляются и предупреждений при их компиляции не возникает.

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

тип_функции имя_класса :: имя_метода (список_формальных_параметров)

{тело метода}

Для класса array на внешнем уровне можно определить функции ReadMas и WriteMas, поскольку они содержат циклы.

// Листинг 11. Определение метода класса на внешнем уровне

class array

{ …

public:

….

void ReadMas();

void WriteMas();

};

void array::ReadMas()

{ cout<<"Ввод массива";

for (int i=0;i<n;i++)

cin>>mas[i];

}

Хотелось бы отметить, что определение функций вне тела класса не несет дополнительных возможностей (если не учитывать возникновения некритичных предупреждений времени компиляции). Однако, при внешнем определении методов класса определение класса остается неизменным, а в определения функций можно вносить изменения.

3.5. Статические компоненты классов

Для изучения особенностей объявления компонент класса в языке С++ рассмотрим еще один класс, назовем его «клиент банка». В этом классе опишем основные характеристики, важные с точки зрения функционирования некоторой информационной системы по учету клиентов банка, а также основные операции, которые выполняются над данными о клиенте.

//Листинг 12. Класс «клиент банка»

class client

{ char *name; //ФИО клиента

char numb[10]; //номер счета клиента

float value; //сумма на счету

float percent; //величина процентной ставки для клиента

public:

client(char* s="Без имени",char *n="N0000",float x=0) //конструктор

{ int k=strlen(s);

name=new char[k+1];

strcpy(name,s);

strcpy(numb,n);

value=x;

percent=0.1;

}

void PrintClient() //функция вывода информации о клиенте на экран

{ cout<<"\nВывод инф-ии о клиенте\n"<<

name<<'\t'<<numb<<'\t'<<value;

}

void ReadClient() //функция ввода информации о клиенте с клавиатуры

{ cout<<"\nВвод инф-ии о клиенте\n";

cin>>name>>numb>>value;

}

void ChangePercent(float p) //функция изменения процентной ставки

{ percent=p; }

void Add(float dx) //функция изменения суммы на счету

{ if (value+dx>0)

value+=dx;

else

cout<<”Нельзя снять такую сумму со счета”;

}

void AddPercent() //функция вывода начисления процентов на вклад

{ value*=percent+1; }

~client() { delete [] name;} //деструктор

};

main()

{client c(“Иванов И.И.”,”N12345”,1000); //определяем объект класса client

c.PrintClient(); //выводим информацию л клиенте на экран

c.Add(2000); //добавляем на счет клиента 2000

c.PrintClient();

c.ChangePercent(0.05); //изменяем процентную ставку

c.AddPercent(); //начисляем проценты на сумму вклада

c.PrintClient();

}

В последнем примере для класса «клиент банка» определены ряд наиболее существенных характеристик, которые объявлены частными компонентными данными, а также несколько общедоступных методов, позволяющих обрабатывать эти характеристики. Если не принимать в расчет иллюстративный характер приведенного примера, а, следовательно, и недостаточное количество компонентных данных и методов в классе для его практического использования, у класса client есть еще один недостаток, который делает эту программную модель не вполне соответствующей реальному субъекту – клиенту банка. Если обратить внимание на компонент percent, то можно отметить, что процентная ставка в реальности вводится не для каждого клиента по отдельности, а является характеристикой банка и для всех клиентов конкретного банка является одинаковой. В связи с этим необходимо определить компонент percent таким образом, чтобы он хранился в памяти в единственном экземпляре при любом количестве объявленных объектов класса client, а его значение было бы общим для всех объектов. Этого можно добиться, объявив данный компонент статическим. Для этого в теле класса необходимо определить компонент следующим образом:

static тип имя_статического_компонентного_данного;

Ключевое слово static определяет компонент статическим. Основное свойство статического компонентного данного заключается в том, что память под него выделяется единственный раз в программе, причем еще до определения объектов данного класса. Для выделения памяти под статический элемент данных класса необходимо вне класса на внешнем уровне программы поместить инициализатор статического компонента вида

тип имя_класса :: имя_статического_компонентного_данного=выражение;

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

При создании объектов класса память под статический элемент данных не выделяется, все объекты работают с единственным статическим компонентом. Обращаться к статическому компоненту класса можно как к обычному компоненту через имя уже существующего объекта, словно он является частью этого объекта. При этом необходимо учитывать, что, обращаясь к компонентному данному через имя одного объекта, мы изменяем его значение и для всех остальных объектов того же класса.

Так как память под статический элемент данных выделяется еще до определения объектов, существует еще один способ обращения к нему:

имя_класса :: имя_статического_компонентного_данного

Такой способ используется для изменения значения статического члена данных в тот момент, когда недоступен ни один из объектов класса.

Необходимо также отметить, что на статические компоненты класса действуют ограничения по области видимости, задаваемые ключевыми словами public, protected и private в теле класса.

Объявим компонент percent класса client статическим.

//Листинг 13. Использование статических компонент в класса

class client

{ …

public:

static float percent;

};

float client::percent=0.1;

main()

{client::percent=0.2; //работать со статическими компонентными данными можно еще до

//определения объектов класса…

client c(“Иванов”,”N12345”,200);

c.percent=0.05; //…а можно и через имя уже определенного объекта

}

Статическими могут быть объявлены не только компонентные данные, но и методы класса. Очевидно, что объявление метода класса статическим носит иное назначение, нежели чем компонентного члена данных, поскольку методы класса, как уже говорилось, и так существуют в памяти в единственном экземпляре. Статические методы класса обычно выступают в качестве интерфейса для работы с частными или защищенными статическими компонентными данными. Если, например, объявить компонент percent в классе client частным, то изменять его значение можно будет только с использованием метода ChangePercent. Однако вызвать метод ChangePercent можно только для конкретного объекта класса, тогда как изменять статические компонентные данные можно и без наличия созданных объектов. Статические методы класса позволяют работать со статическими компонентными данными без использования объектов данного класса. Объявляются такие методы в теле класса через ключевое слово static:

static тип имя_статического_метода( список_формальных_параметров );

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

имя_класса :: имя_статического_метода ( список_фактических_параметров )

Рассмотрим пример с классом «клиент банка».

//Листинг 14. Использование статических компонент в класса

class client

{ …

static float percent;

public:

static void ChangePercent(float p)

{percent=p;

}

};

float client::percent=0.1;

main()

{ //client::percent=0.2; Такое обращение запрещено, т.к. percent- частный компонент

client::ChangePercent(0.1);

client c(“Иванов”,”N12345”,200);

c.ChangePercent=0.05;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]