5.3 Переопределение операций new и delete

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

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


void *operator new(size_t size);

void operator delete (void *);


где void * - ссылка на область памяти, выделяемую под объект,

size - размер объекта в байтах.


Переопределение этих операций позволяет написать собственное

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


5.4 Переопределение операций [], (), ->

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

Переопределение () :

-------------------class one

{

public:

typeout operator()(type1,type2);

};


Вызов:

type1 a; // Вызов оператора совпадает с

type2 b; // синтаксисом вызова функции

one obj; // с именем данного объекта


... obj(a,b) ... эквивалентно obj.operator()(a,b)


Переопределение -> :

------------------class two

{

public: type Y;

};


class one

{

two operator->(); // Операция должна возвращать объект

или two* operator->(); // или ссылку на объект класса two,

}; // в котором определен элемент Y


Вызов:

one obj;


... obj->Y .. эквивалентно (obj.operator->()) ->Y


Переопределение [] : используется для моделирования виртуальных

-------------------- массивов элементов определенного типа.

class text_page

{

char **page; // Массив ссылок на строки

public:

int operator[](char*); // Ассоциативный поиск индекса

// по строке

char* operator[](int); // Выделение строки по индексу

};


5.5 Переопределение операции копирования объектов

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

Kaк известно, определение объекта класса в виде


=


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

Eсли функция возвращает объект, то оператор return также выполняет копирование объекта - операнда в объект назначения.

Taкое копирование не корректно в том случае, если объекты содержат ссылки на другие объекты или переменные в динамической памяти. В этом случае можно воспъльзоваться специальным конструктором копирования, параметром котрого является неявная ссылка на объект - источник, а this указывает на объект приемник. Будучи определенным, он вызывается во всех вышеперечисленных случаях копирования объектов один в другой.

Пример корректного конструктора копирования для класса строк имеет вид:


class string

{

char *s; // Ссылка на строку

int sz; // Длина строки

public: string(string&);// Конструктор копирования

}; // создает копию строки в динамической

// памяти для объекта - приемника

string::string(string& right)

{

s = new char[right->sz];

strcpy(s,right->s);

}

Лекция 6. Производные классы

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

6.1 Вложенные классы

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

Понятие производного класса вводит в систему классов принцип

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

собственные цели и особенности.


Первый случай представляет собой обычный способ построения

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

Он имеет собственное имя (именован), по которому к нему можно обращаться как к объекту. В элементах-функциях нового класса можно

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

класса. Рассмотрим в качестве примера класс man - информация о

человеке, включающая в себя даты рождения и поступления на работу.


class man

{

char name[20]; // Другие элементы класса

char *address;

dat dat1; // Дата рождения

dat dat2; // Дата поступления на работу

public:

void newadr(); // Элемент-функция

man(char*); // Конструктор

}


//----- Функция "Изменить адрес проживания" ----------------void man::newadr()

{

int n;

char s[80]; // Строка нового адреса

if (address != NULL)

delete address; // Освободить память

printf("Введите новый адрес:");

gets(s);

address = new char[strlen(s)+1];// Занять новую память

strcpy(address,s); // Заполнить поле адреса

}


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


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


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

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


class man

{

char name[20]; // Другие элементы класса

dat dat1; // Дата рождения

dat dat2; // Дата поступления на работу

public:

man(char *,char *,char *); // Конструкторы

man(char *);

}

//----- Конструктор класса man с неявным вызовом конструкторов

// для dat1 и dat2 без параметров

//----------------------------------------------------- man::man(char *p)

{

}

//----- Конструктор класса man с явным вызовом конструкторов

// для dat1 и dat2 с параметрами

//--------------------------------------------------------- man::man(char *p,char *p1, char *p2) : dat1(p1), dat2(p2)

{ ¦ ¦ ¦

// --- Тело конструктора --- ¦ ¦ ¦

} ¦ ¦ ¦

Вызов конструктора для ------------------ ¦ ¦

вложенного объекта dat1 ¦ ¦

В качестве параметра передается ------------- ¦

строка - второй параметр вызова ¦

конструктора для класса man Вызов конструктора для

вложенного объекта dat2


void main ------ Строка конструктора man

{ ¦

man JOHN("John","8-9-1958","15-1-1987");

} ¦ L------ Строка передается

Строка передается конструктору объекта

конструктору объекта dat2 в объекте man

dat1 в объекте man



Информация о работе «Объективное программирование»
Раздел: Информатика, программирование
Количество знаков с пробелами: 61028
Количество таблиц: 0
Количество изображений: 0

Похожие работы

Скачать
14044
1
2

... обучающих программ Обучающие программы, построенные на бихевиористской основе, подразделяют на: а) линейные, разработанные Скиннером, б) разветвленные программы Н. Краудера. 1. Линейная система программированного обучения, первоначально разработанная американским психологом Б. Скиннером в начале 60-х гг. ХХ в. на основе бихевиористского направления в психологии. ·  Он выдвинул следующие ...

Скачать
93027
12
0

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

Скачать
109055
0
0

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

Скачать
165676
21
12

... отбора. ГЛАВА II. ЦЕЛЬ, ЗАДАЧИ, МЕТОДЫ И ОРГАНИЗАЦИЯ ИССЛЕДОВАНИЯ   2.1 Цель и задачи исследования Цель исследования - повышение эффективности физической подготовки вратарей учебно-тренировочных групп на соревновательном этапе. В процессе реализации поставленной цели решались следующие основные задачи: 1.     Изучить особенности возрастного развития двигательных способностей футболистов ...

0 комментариев


Наверх