Смекни!
smekni.com

Объективное программирование (стр. 3 из 10)

const int n=5;

n++; // Запрещено

int xxx(const int m)

{

m++; // Запрещено

}

Применительно к ссылке const может использоваться в двух вариантах, применительно к самой ссылке (адресу) и применительно к указуемому значению:

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

const char * p;

p = "1234567890"; // Разрешено присваивание ссылке

p + =3; // Разрешена модификация ссылки

*(p+3) = '3'; // Запрещено присваивание по ссылке

(*p)++; // Запрещен инкремент по ссылке

- при использовании const применительно к ссылке запрещается менять значение ссылки после инициализации, в том числе средствами адресной арифметики. Такая ссылка называется постоянной ссылкой на объект:

char const* p = "1234567890";

char c;

(*p) = '3'; // Разрешено присваивание по ссылке

p++; // Запрещено изменение значения

c = *(p+3); // самой ссылки

Полная фиксация ссылки и адресуемого ею объекта возможна в виде

const char const* p = "1234567890";

2.11 Общие замечания о дополнениях в Си++

----------------------------------------

Основные отличия Си++ от "классического" Си:

- структура (struct) приближена по свойствам к базовым типам

данных (char,int);

- введено понятие элемента-функции. Элементы-функции играют

роль своеобразного "интерфейса" для использования определенной

программистом структуры;

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

Все эти новые свойства необходимы при определении понятий

класса и объекта.

Лекция 3. Классы. Объекты. Конструкторы и деструкторы

----------------------------------------------------

3.1.Понятие класса и объекта в Си++

----------------------------------

В самом простом виде класс определяется в Си++ как структура, работа с элементами которой возможна только через элементы-функции. В отличие от структуры класс имеет "приватную" (личную) часть, элементы которой не могут быть доступны иначе как через другие элементыфункции, и "публичную" (общую) часть, элементы

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

как класс (структура):

Определение структуры Определение класса

------------------------- -----------------------------------struct dat class dat

{ { // Приватная часть

int day,month,year; int day,month,year;

public: // Публичная часть

void SetDat(int,int,int); void SetDat(int,int,int);

void SetDat(char *); void SetDat(char *);

} аа}

void main() void main()

{ {

// Опред-ние переменных a,b // Опред-ние объектов a,b класса dat

dat a,b; dat a,b;

a.day = 5; // Непосредственное использование

a.month = 12; // приватной части объекта запрещено

bAA.SetDat("12,12,1990"); b.Setdat("12,12,1990");

} }

"Приватная" часть класса не обязательно должна следовать в начале определения класса. Для ее обозначения в произвольном месте определения класса можно использовать служебное слово private.

Tаким образом в первом приближении класс отличается от структуры четко определенным интерфейсом доступа к его элементам.

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

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

- статические (внешние), создаваемые в статической памяти программы и существующие в течение всего времени работы программы;

- автоматические, создаваемые в стеке в момент вызова функции и уничтожаемые при ее завершении;

- динамические, создаваемые и уничтожаемые в свободной памяти задачи в моменты вызова функций malloc() и free() или выполнения операторов new и delete.

Соответственно в программе возможно определение статических, автоматических и динамических объектов одного класса:

class dat

{ ....... }

dat a,b; // Статические объекты

dat *p; // Ссылка на объект

void main()

{

dat c,d; // Автоматические объекты

p = new dat; // Динамический объект

...

delete p; // Уничтожение динамического объекта

} <---------------------// Уничтожение автоматических объектов

3.2. Создание и уничтожение объектов.

Конструкторы и деструкторы

-------------------------------------

Процесс создания и уничтожения объектов класса ассоциируется

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

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

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

элементы-функции класса и имена их совпадают с именем класса.

Конструкторов для данного класса может быть сколь угодно много,

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

один и имеет имя ~<имя класса>.

С процессом создания объектов связано понятие их инициализации. Инициализировать объекты обычным способом нельзя. Их инициализация осуществляется либо явным присваиванием (копированием)

другого объекта, либо неявным вызовом конструктора. Если

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

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

- для статических объектов - конструктор вызывается перед

входом в main(), деструктор - после выхода из main(). Конструкторы вызываются в порядке опредлеления объектов, деструкторы - в

обратном порядке;

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

входе в функцию (блок), деструктор - при выходе из него;

- для динамических объектов - конструктор вызывается при выполнении оператора new, деструктор - при выполнении оператора delete.

В Си++ возможно определение массива объектов класса. При этом конструктор и деструктор вызываются для каждого элемента массива и не должны иметь параметров. При выполнении оператора delete для ссылки на массив объектов необходимо также указывать его размерность. Конструктор для массива объектов должен быть без параметров.

//--------------------------------------------------------#include <stdio.h>

#include <dos.h>

static int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

class dat

{

int day,month,year;

public:

dat(int,int,int); // Конструктор с параметрами

// (возможно умолчание)

dat(char *); // Конструктор с одним параметром

dat(); // Конструктор без параметров

~dat(); // Деструктор

};

//------- Конструктор с параметром - текстовая строка ---------dat::dat(char *s)

{

int i;

char ss[80];

strcpy(ss,s);

for (i=0; ss[i] !=0; i++)

if (ss[i]=='-') ss[i]=','; // Замена '-' на ','

sscanf(ss,"%d%d%d",&day,&month,&year);

}

// Конструктор с тремя параметрами (по умолчанию 0 - текущая дата)

dat::dat(int d=0, int m=0, int y=0)

{

struct date x;

getdate(&x); // Стандартная функция получения

// текущей даты

// Проверка на значение по умолчанию

year = (y == 0) ? x.da_year : y;

month= (m == 0) ? x.da_month: m;

day = (d == 0) ? x.da_day : d;

}

//------ Конструктор без параметров --------------------------dat::dat()

{

struct date x;

getdate(&x); // Стандартная функция получения

// текущей даты

year = x.da_year ;

month= x.da_month;

day = x.da_day ;

}

//------ Деструктор ------------------------------------------dat::~dat()

{

printf("Дата ==> %2d-%2d-%4d&bsol;n",day,month,year);

}

//------------------------------------------------------dat a("12-12-1990"); // Внешняя переменная - конструктор

// вызывается перед main()

dat b[10]; // Массив объектов - конструктор без

// параметров вызывается перед main()

void xxx(dat &p)

{

dat c(12,12); // Вызывается Конструктор dat(int,int,int)

// для автоматического объекта

dat d = p; // Конструктор для автоматического объекта не

... // вызывается, т.к. объект инициализируется

... // копированием

} // При выходе из функции вызываются деструкторы

// для объектов c и d

void main()

{

int i,n;

scanf("%d",&n);

dat *p = new dat[n]; // Создание массива динамических объектов // конструктор без параметров явно вызывается

for (i=0; i<10; i++) // n раз

xxx(b[i]); // При вызове неявно передается ссылка на b[i]

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

xxx(p[i]) // При вызове неявно передается ссылка на p[i]

delete[n] p; // Уничтожение массива динамических объектов // деструктор явно вызывается n раз

} // Деструктры для a и b[10] вызываются после

// выхода из main()

}

3.3 Ограничение доступа к объектам класса. Дружественность.

----------------------------------------------------------

Выше было дано формальное определение класса. Содержательная его сторона состоит в том, что класс выступает в Си++ как определенный программистом тип данных. Такой тип данных включает в себя:

- описание структуры объектов класса. Объект класса представляет собой совокупность элементов (структуру), каждый из которых является переменной некоторого типа или объектом ранее определенного класса;

- описание множества допустимых операций над объектом класса, которые представлены элементами-функциями;

- описание процедур создания и уничтожения объекта класса (конструктор и деструктор).

При этом внутренняя структура объектов (описанная в "приватной" части класса) доступна только элементам-функциям. Наоборот, "публичная" часть определения класса - это описание той части объекта, к которой возможен доступ из любого места программы, если доступен сам объект. Данное ограничение позволяет исключить некорректное использование объектов класса, как случайное, так и умышленное. Возможные ошибки, связанные с неправильным "поведением" объектов класса, локализуются таким образом в определении самого класса, а не в использовании его объектов.