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

Объект класса выходит

из области видимости

Создается С++ вызывает конструктор выделяет программа вызывает или удаляется .С++

Объект конструктор требуемое количество функции-члены вызывается деструктор

Класса класса объекта памяти класса который освобождает

Выделенную память

0 t+1 t+2 t+3 t+n

Рис. 2.5. события, обычно происходящие с объектами во время его существования

Глобальные объекты класса

Конструктор глобальных объектов класса вызывается до начала выполнения функции main().

Это обеспечивает инициализации всех глобальных объектов до формального начала выполнение программы.

ПРИМЕР:

При использовании классаTTime (листинг 2.18 и 2.19) глобальное объявление

TTime today;

Создает глобальный объект today класса TTime. До вызова main() C++ вызывает для today конструктор TTime по умолчанию, который устанавливает в объекте текущую дату и время.

Для инициализации глобального объекта класса TTime каким-либо определенным датой и времени следует использовать следующее объявление:

TTime sTime(9, 4, 1953, 10, 45);

Наличие списка инициализаторов в круглых скобках С++ вызовет перегруженный конструктор TTime (строки 17-18 листинга 2.18), который инициализирует stime значением даты и времени 4 сентября 1953 года, 10:45.

это действие выполнится до того, как будет вызвана main().

Деструкторы глобальных объектов класса вызываются как обычно в качестве части кода завершения программы, после отработки функций завершения, заданных вызовами функции exit(). Деструкторы не вызываются, если программа заканчивается с помощью обращения к abort().

Локальные объекта класса

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

Как и переменных обычных типов, данные-члены автоматического объекта класса сохраняются в стеке.

В функции

void anyFunction(void)

{

TTime now;

// Инициализируется при каждом //вхождении в функцию

….

}

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

Когда функция завершает работу, С++ вызывает деструктор TTime для объекта now.

(что дает объекту возможность “убрать” за собой до того, как он выйдет из видимости.)

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

Указатель на объекты

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

ПРИМЕР:

// указатель pToday на объект класса //типа TTime

TTime *pToday;

Это объявление м.б. как глобальным в функции.

// инициализация указателя pToday до

//его использования с помощью new

pToday = new TTime;

// с помощью оператора new выделяется пространство в куче для объекта типа TTime.

Адрес первого байта этого объекта присваивается pToday.

С++ вызывает конструктор объекта по умолчанию, который инициализирует объекта текущими датой и временем.

Для использования другого конструктора добавьте параметры после имени класса.

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

pToday=new Time(9, 4, 1953, 10,45);

использование указателей на объекты класса для ссылки на член адресуемого объекта можно

  • с помощью оператора ->

  • оператора *

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

Пример:

//вывод даты и времени объекта класса

//TTime, на который ссылается pToday:

pToday->Display();

Пример:

Sp = ( *pToday).GetSTime();

//присваивание переменной sp (которая //объявлена, как const char *sp;) результата функции-//члена GetSTime() для объекта //класса, на который ссылается //pToday.

Sp = pToday->GetSTime();

//легче,выполняется аналогично .

С++ вызывает деструкторы динамических объектов класса при их удалении. Пример:

delete pToday;

//удаление объекта, на который //ссылается pToday, освобождение //памяти этого объекта в куче.

//перед разрушением объекта С++ //вызывает деструктор класса.

Не путайте жизнь указателя с жизнью объекта, на который он ссылается. Глобальный указатель существует до тех пор, пока программа не завершится, но он может ссылаться на множество объектов класса, создаваемых с помощью new и удаляемых с помощью delete. Аналогично, автоматически указатели, объявленные локальными в функции, создаются при выполнении функции и уничтожаются при ее завершении. Но объекты, на которые ссылаются указатели, имеют глобальную область действия и должны удалятся явным образом.

В функции f(), если вы вызовете new для создания объекта в куче, этот объект останется в памяти даже после завершения функции. Вы должны явным образом удалять любой подобный объект, если вы не хотите, чтобы он оставался в памяти после возврата из функции.

Ссылочные объекты

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

Объекты класса могут объявляться как ссылки. Предположим, вы объявили глобальный объект класса TTime:

TTime today;

// глобальный объект today

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

TTime &rToday = today ;

// ссылка на today

Ссылка rToday – алиас для today, и можете использоваться вместо today. Например, каждый из следующих двух операторов выведет дату и время:

rToday.Display();

today.Display();

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

Совет

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

Объекты-параметры

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

Классы  это типы данных, и вы можете объявлять параметры функции, имеющие тип классов так же, как и параметры других типов.

1. Пример передачи по значению:

//реализация ф-ции

void anyFunction(TTime t)

// параметр t типа TTime

{

t.Display();

//вызывается функция-член Display() объекта t для вывода даты и //времени, хранящихся в параметре

}

пример:

//вызов ф-ции

// объявление объекта класса TTime

TTime today;

anyFunction(today);

Функции также могут объявлять в качестве параметров указатели на класс.

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

В таких случаях предпочтительней параметры-указатели.

2. Пример передачи с параметрами-указателями:

void anyFunction(TTime *tp)

{

tp->Display();

}

вызов этой ф-ции

anyFunction(&today);

3. Пример передачи с с использованием ссылочного параметра (на объект класса TTime):

void anyFunction(TTime &tr) // tr—ссылочный параметр

{

tr.Display();

// вызов Display() для объекта, на //который ссылается tr

// передача объекта класса TTime

//в качестве ссылочного параметра

anyFunction(today);

недостаток ссылочных параметров – такой оператор похож на передачу аргумента today по назначению.

Факт передачи в anyFunction() ссылки на today из текста совершенно не очевиден.

Объекты  результаты функций

Функции могут возвращать объекты классов непосредственно в качестве указателей или как ссылки.

1.Пример: функция, возвращает объект класса TTime

TTime newTime(void)

{

// Локальный объект t (автоматически инициализированный вызовом конструктора в начале выполнения функции) возвращается непосредственно.

TTime t;

return t;

}

//вызов ф-ции

// результат функции newTime() //копируется в anTime

TTime anTime = newTime();

Такой подход имеет мало преимуществ

2.Пример: функция, возвращает указатели на объекты класса

TTime *newTimeP(void)

{

TTime *P = new TTime;

// выделение и инициализация //объекта

return P;

// возвращение адреса объекта в //качестве результата функции

//объект, на который ссылается этот //указатель, глобальный, сл-но можно вернуть указтель

}

//вызов ф-ции

TTime *tp =newTimeP();

//получение нового объекта и //присвоение его адреса указателю tp

3.Пример: функция, возвращает ссылки на объекты класса

//ссылочная функция для ссылки на //существующий глобальный объект //Ttimetoday:

TTime &newTimeR(void)

{

return today;

}

//вызов ф-ции

//объявление ссылки на TTime

//присвоение ей результата //newTimeR()

TTime &tr = newTimeR();

//ccылка tr— псевдоним для today

newTime R().Display();

Это полезно в случае, если функция подобная newTimeR(), выполняет операцию поиска с возможным возвратом ссылки на один из нескольких объектов класса TTime, исходя из неких указанных критериев.

Массивы объектов класса

Пример: массив из 10 элементов объектов TTime

TTime tenTimes[10];

//С++ вызывает 10 раз конструктор по умолчанию TTime, //инициализируя таким образом объекты tenTimes[0]tenTimes[9] //текущими датой и временем

строгое правило: объекты класса, Которые, будут содержать массив, должны иметь конструкторы по умолчанию.

Пример 2.22 OB.CPP (массивы и конструкторы по умолчанию)

(используется класс TTime, определенный ранее в TIME6.H)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

//объявляется массив tar из

//шести объектов TTime

7: TTime tar[6];

8:

9: for (int i = 0; i < 6; i++)

// шесть одинаковых дат и времен

10: tar[i].Display();

11: return 0;

12: }

Для вызова различных конструкторов, надо явным образом инициализировать каждый элемент массива.

Пример 2.23 OB1.CPP (объявление массивов и альтернативных конструкторов)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

//объекты массива

//инициализируются конструкторами,

//указателями в скобках

7: TTime tar[6] = {

// с помощью вызова конструктора по //умолчанию

8: TTime(),

//вызов перегруженных

// конструкторов

9: TTime(8),

10: TTime(8, 1),

11: TTime(8, 1, 1996),

12: TTime(8, 1, 1996, 8 ),

13: TTime(8, 1, 1996, 8, 30),

14: };

15: for (int i = 0; i < 6; i++)

16: tar[i].Display();

17: return 0;

18: }

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

Этот прием слишком громоздкий для широкого применения на практике за исключением небольших по размеру массивов.

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

Пример 2.24. OB3.CPP (поддержка динамических массивов объектов класса)

1: #include <iostream.h>

2: #include <stdio.h>

3: #include “time6.h”

4:

5: main()

6: {

// tarP - указатель на объект класса //TTime

7: TTime *tarP;

8:

9: tarP = new TTime[6];

// Создание динамического массива

10: for (int i = 0; i < 6; i++)

11: tarP[i].Display();

12: delete[] tarP;

// особая форма delete[]

//вызов всех деструкторов (для //каждого объекта в массиве) при

//удалении динамического массива

// объектов класса

13: return 0;

14: }

Замечание

В прошлых версиях С++ необходимо было указывать число элементов вудаляемом массиве объектов класса и вам пришлось бы использовать операторы вида delete[6] tarrayP; для удаления массива из шести объектов класса TTime, на который ссылается tarrayP. Применение этого приема ныне не допускается, и Borland С++ игнорирует любые значения внутри скобок delete[]. Если вы укажете размер массива в скобках, компилятор выдаст вам предупреждение “array size for ‘delete” ignored in function x() ” (Размер массива для delete проигнорирован в функции x()).

**************************************************************

ИТОГИ

Элементы –поля и методы класса.

Поля – данные класса (данные-члены).

Методы – функции класса (ф-ции члены).

сlass <bvz> {

[private:]

<описание скрытых эл-тов >

Public:

<описание доступных эл-тов >

};

Поля класса:

  • м.б.любого типа;

  • м.б. описаны с модификатором const, инициализируются один раз (конструктором) и не м. изменяться;

  • м.б. описаны с модификатором static ( не auto, extern, register).

Static-статическая переменная. Время жизни – постоянное. Инициализация – один раз при первом выполнении оператора, инициализирующего переменную. М.б. лок. , глоб.

Auto- автоматическая переменная. Память выделяется в стеке, инициализация – столько раз, сколько нужно. Освобождение – при выходе из блока. Время жизни : от начала описания до конца блока. Для лок-ных – по умолчанию, для глоб. – не исп-ся.

Extern- переменная объявлена в другом месте программы (др. модуль, или дальше в программе). Исп-ся для создания пер-ных, доступных во всех модулях.

Register- аналог Auto. Память выделяется в регистрах процессора

ОПИСАНИЕ ОБЪЕКТОВ

Конкретные переменные типа «класс» называются экземплярами класса, или объ­ектами. Время жизни и видимость объектов зависят от вида и места их описания и подчиняются общим правилам C++:

TTime V; // Объект класса TTime с параметрами по

TTime Super(200, 300); // Объект с явной инициализацией TTime stado[100]: // Массив объектов с параметрами по

TTime *beavis = new monstr (10); // Динамический объект

//(второй параметр задается по умолчанию

TTime &butthead = V;

// Ссылка на объект

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

Дocmyn к элементам объекта аналогичен доступу к полям структуры. Для этого используются операция . (точка) при обращении к элементу через имя объекта и операция -> при обращении через указатель, например:

int n = V.get();

stado[5].draw;

cout « beavis->get();

Обратиться таким образом можно только к элементам со спецификатором publiс. Получить или изменить значения элементов со спецификатором private можно только через обращение к соответствующим методам.

Можно создать константный объект, значения полей которого изменять запре­щается. К нему должны применяться только константные методы:

class monstr{

int get_h() const {return h:}

}:

const monstr D(0,0);

// Константный объект

cout « D.get_h():

Константный метод:

  • объявляется с ключевым словом const после списка параметров;

  • не может изменять значения полей класса;

  • может вызывать только константные методы;

  • может вызываться для любых (не только константных) объектов.

Рекомендуется описывать как константные те методы, которые предназначены для получения значений полей.

Указатель this

Каждый объект содержит свой экземпляр полей класса.

Методы класса находят­ся в памяти в единственном экземпляре и используются всеми объектами совме­стно, поэтому необходимо обеспечить работу методов с полями именно того объ­екта, для которого они были вызваны. Это обеспечивается передачей в функцию скрытого параметра this, в котором хранится константный указатель на вызвав­ший функцию объект.

Указатель this неявно используется внутри метода для ссылок на элементы объекта.

В явном виде этот указатель применяется в основ­ном для возвращения из метода указателя (return this;) или ссылки (return *this;) на вызвавший объект.

Для иллюстрации использования указателя this добавим в приведенный выше класс monstr новый метод, возвращающий ссылку на наиболее здорового (поле health) из двух монстров, один из которых вызывает метод, а другой передается ему в качестве параметра (метод нужно поместить в секцию public описания класса):

Monstr & thebest(monstr &M){

1f( health > М.health) return *this; return M;

... monstr V(50), Super(200);

// Новый объект Best инициализируется значениями полей Super:

monstr Best = V.the_best(Super);

Указатель this можно также применять для идентификации поля класса в том случае, когда его имя совпадает с именем формального параметра метода.

Другой способ идентификации поля использует операцию доступа к области видимости:

void cur(int h,int am){

this -> h += h;

// Использование this

monstr:: am += am;

// Использование операции ::

Конструкторы

Конструктор предназначен для инициализации объекта и вызывается автомати­чески при его создании.

основные свойства конструкторов.

  • Конструктор не возвращает значение, даже типа void.

  • Нельзя получить указа­тель на конструктор.

  • Класс может иметь несколько конструкторов с разными параметрами для раз­ных видов инициализации (при этом используется механизм перегрузки).

  • Конструктор, вызываемый без параметров, называется конструктором по умолчанию.

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

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

  • Конструкторы не наследуются.

  • Конструкторы нельзя описывать с модификаторами const, virtual и static.

  • Конструкторы глобальных объектов вызываются до вызова функции main Локальные объекты создаются, как только становится активной область их действия. Конструктор запускается и при создании временного объекта (на­ пример, при передаче объекта из функции).

  • Конструктор вызывается, если в программе встретилась какая-либо из син­таксических конструкций:

имя_класса имя_объекта [(список параметров)];

// Список параметров не должен быть пустым

имя_класса (список параметров);

//созд. Объект без имени

Имя_класса имя_объекта=выр-ние;

//создается объект без имени и копируется

СТАТИЧЕСКИЕ ЭЛЕМЕНТЫ КЛАССА

Статические поля

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

особенности статических полей.

□ Память под статическое поле выделяется один раз при его инициализации независимо от числа созданных объектов (и даже при их отсутствии) и ини­циализируется с помощью операции доступа к области действия, а не опера­ции выбора (определение должно быть записано вне функций):

class A{ public:

static int count;

// Объявление в классе

int A::count;

// Определение в глобальной области

// По умолчанию инициализируется нулем

int Account = 10;

// Пример инициализации произвольным значением

□ Статические поля доступны как через имя класса, так и через имя объекта:

А *а, b;

cout « Account « a->count « b.count;

// Будет выведено одно и то же

  • На статические поля распространяется действие спецификаторов доступа, поэтому статические поля, описанные как private, нельзя изменить с помо­щью операции доступа к области действия, как описано выше. Это можно сделать только с помощью статических методов .

  • Память, занимаемая статическим полем, не учитывается при определении размера объекта с помощью операции sizeof.

Статические методы

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

class A{

static int count;

// Поле count - скрытое public:

static void inc_count(){ count++: }

А::int count; // Определение в глобальной области void f(){

А а;

// a.count++ - нельзя, поле count скрытое

// Изменение поля с помощью статического метода:

a.inc_count(); // или A::inc_count();

Статические методы не могут быть константными (const) и виртуальными (virtual).

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