- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
- •Оглавление
- •Предисловие
- •Введение
- •1.1. Понятие класса и объекта. Инкапсуляция
- •1.2. Определение классов. Компоненты. Доступность
- •Class_key /*class_id*/ { /*members_list*/ };
- •Value_type class_id::function_id(parameters) {statements}
- •CPoint point1(100,70); // локальный объект
- •Static cPoint point3(50,120); // статический объект
- •Class_id(parameters) /*:initializer_list*/ {/*statements*/}
- •CString(const char *);
- •Delete[] __thematrix;
- •1.4. Обращение к компонентам объектов
- •1.5. Статические и нестатические компоненты классов
- •1.7. Указатель this
- •В опросы для самопроверки
- •2. Механизм наследования. Полиморфизм
- •2.1. Формы наследования. Базовые и производные классы
- •Class_key class_id: inheritance_specifier base_class_id {member_list};
- •2.3. Абстрактные классы
- •2.4. Множественное наследование и виртуальные классы
- •2.5. Преобразование динамических типов. Динамическая идентификация типов
- •Catch ( std::bad_cast & ) { // обработка исключения
- •Return 0;
- •Вопросы для самопроверки
- •3. Дружественные функции и классы
- •3.1. Дружественные функции
- •3.2. Дружественные классы
- •Вопросы для самопроверки
- •4. Механизм вложения
- •4.1. Вложенные классы
- •4.2. Локальные классы
- •Вопросы для самопроверки
- •5. Объектная модель и шаблоны
- •5.1. Определение, описание и инстанцирование шаблонов
- •::Function_id(function_parameter_list) { statements }
- •5.2. Параметры и аргументы шаблонов
- •Class identifier typename identifier
- •// Key, Data – параметры-типы (типы ключа и данных отображения)
- •// Container – контейнер, где содержится информация отображения class сMap {
- •Class MyTemplate
- •Int array[10]; struct Structure { int m; static int sm; } str;
- •5.3. Шаблоны компонентных функций
- •Value_type function_template_id(function_parameter_list) { statements }
- •::Function_template_id(function_parameter_list) { statements }
- •5.4. Специализация шаблонов
- •Вопросы для самопроверки
- •6. Перегрузка операций
- •Value_type operator @ (parameter_list);
- •Value_type operator @ (parameter_list) { statements }
- •Return fail();
- •6.3. Перегрузка бинарных операций
- •Value_type operator @ (parameter); // компонентная функция
- •Value_type operator @ (parameter, parameter); // глобальная функция friend value_type operator @ (parameter, parameter); // дружественная функция
- •Return *this;
- •Return *this;
- •/* Присваиваем собственные данные класса d */
- •6.4. Перегрузка операций управления памятью
- •Typedef void (*new_handler) ();
- •Extern new_handler set_new_handler( new_handler new_p );
- •Void operator delete(void * memory) {
- •... // Специальная обработка пользователя ::operator delete(memory); // освободить память
- •Вопросы для самопроверки
- •7. Механизм исключений
- •Throw expression
- •7.3. Специальные средства поддержки механизма исключений
- •Unexpected_function set_unexpected(unexpected_function func_name);
- •Typedef void (* unexpected_function) ();
- •Extern char * __throwExceptionName; extern char * __throwFileName; extern unsigned __throwLineNumber;
- •Вопросы для самопроверки
- •8. Подсчет ссылок
- •8.1. Назначение механизма подсчета ссылок
- •8.2. Контекстно-независимая модель счетчика ссылок
- •8.4. Внедрение подсчета ссылок в существующий класс
- •Вопросы для самопроверки
- •9. Стандартная библиотека шаблонов (stl)
- •9.1. Назначение и архитектура stl
- •9.2. Последовательные контейнеры
- •Class vector {
- •// Определение итераторов
- •Sort(first,last); // сортировка вектора в диапазоне итераторов
- •Ifstream ifile ("example.In"); ofstream ofile ("example.Out");
- •OutputIterator copy(
- •InputIterator first, InputIterator last, OutputIterator result );
- •// Заполнение списка
- •Operator- (int)
- •Operator- (random access iterator) operator[] (int)
- •InputIterator find(InputIterator first, InputIterator last, const t & value);
- •InputIterator find(InputIterator first, InputIterator last, const t & value)
- •Return first;
- •OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
- •Return result;
- •OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
- •Return result;
- •Void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
- •__Quick_sort_loop(first, last, comp); __final_insertion_sort(first, last, comp);
- •T accumulate(InputIterator first, InputIterator last, t init, Function f);
- •V.Push_back(2); V.Push_back(5);
- •9.5. Функторы
- •T operator()(const t & X) const { return -X; }
- •9.7. Адаптеры
- •S1.Push(1); s1.Push(5);
- •// Записать в вектор числа 1 2 3 4
- •// Сортировать по неубыванию
- •// Записать в вектор числа 4 6 10 3 13 2
- •Вопросы для самопроверки
- •Заключение
- •Библиографический Список
- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
1.7. Указатель this
Всякая нестатическая компонентная функция при вызове получает указатель на тот объект, который является инициатором ее вызова. Этот указатель в С++ носит предопределенное имя this и передается в функцию первым неявным аргументом. Благодаря указателю this компонентные функции получают доступ к данным объекта и другим его компонентам. Любое обращение к компоненту в виде member_id внутри компонентной функции фактически означает this–>member_id (для упрощения записи this–> просто опускается).
Указатель this определяется автоматически, причем формат его определения зависит от того, какого рода компонентная функция вызывается. Так, если вызывается константная функция, то this определяется как
const class_id * const this = &this_object_id,
где this_object_id – имя текущего объекта.
Если вызываемая функция имеет модификатор volatile или const volatile, то определение указателя this будет таким:
volatile class_id * const this = &this_object_id // для volatile
const volatile class_id * const this = &this_object_id // для const volatile
Указатель this доступен только в нестатических компонентных функциях; статическим функциям он не передается, поскольку они работают на уровне класса, а не отдельных объектов.
Явное использование указателя this редко бывает необходимым, однако все же есть ситуации, где без него трудно написать эффективный код. Одной из них является работа со списками. Для иллюстрации ниже в упрощенном виде определяется класс для представления элемента односвязного списка и демонстрируется использование указателя this.
class CListElement { // определение класса
public:
CListElement(int data) { __data=data; } // конструктор
void AddElement(); // добавление элемента в список
...
private:
int __data; // данные
CListElement * __pnext; // указатель на следующий элемент
static CListElement * __phead; // первый элемент (голова списка)
};
... // реализация класса
void CListElement::AddElement() {
if ( __phead ) // список не пуст?
__phead –> __pnext = this; // этот элемент перед головой
this –> __pnext = NULL; // впереди пока нет элементов
__phead = this; // этот элемент - голова
}
...
Изложенный в данной главе материал позволяет понять базовые принципы организации автономных классов, определение объектов таких классов и доступ к их компонентам. Однако, для практики большой интерес представляют не только классы, но и отношения между ними, а также способы формирования новых классов на основе существующих. Одним из таких способов является наследование, которому посвящена глава 2.
В опросы для самопроверки
Охарактеризуйте понятие класса. Чем класс отличается от структуры?
Какие компоненты могут входить в класс?
Почему определение класса обычно выносится в заголовочный файл, а реализация – в отдельный cpp-файл?
Для чего необходимо предварительное объявление класса? Каким образом оно осуществляется? Приведите общий формат и пример.
В классе CMatrix, описывающем прямоугольные матрицы, имеется компонент static const size_t __max_size. Как правильно проинициализировать этот компонент?
В классе CNamedPointer, описывающем именованные указатели, есть компонент const string&__name, содержащий имя указателя. Выделите недостатки такого способа задания компонента для хранения имени.
Как правильно инициализировать константный указатель на константу, входящий в число компонент класса? Приведите пример.
Имеется оператор (pseq->*mbr_func_ptr)(6); Выведите из него возможный вариант определения имени mbr_func_ptr, учитывая, что pseq – указатель на объект класса CSequence.
Пусть требуется определить класс поименованных векторов и пусть всем объектам этого класса, формируемым конструктором по умолчанию, надо давать умалчиваемое значение имени __default_name. Как можно определить компонент __default_name? Приведите эскиз класса векторов, исключив несущественные компоненты.
Вызов функции CSequence::AlreadyPrinted() встречается в следующем контексте: if ( !seq.AlreadyPrinted() ) seq.print(); Восстановите возможный прототип этой функции, полагая, что она не имеет значений параметров по умолчанию.
Почему в public-секцию класса нежелательно вводить компонентные данные? Поясните ответ примером.
Имеется класс CSomeClass. Правильно ли определен заголовок конструктора копирования этого класса: CSomeClass(CSomeClass cloned_object)? Обоснуйте ответ.
Какие действия происходят при выполнении оператора CBitSequence * pseq = new CBitSequence(8); если CBitSequence – имя некоторого класса?
Опишите алгоритм выполнения оператора delete[] p; где p – указатель на массив объектов некоторого класса.
Какие новые свойства придает конструктору ключевое слово explicit? Приведите пример.
Почему ключевое слово explicit не требуется использовать в конструкторах по умолчанию и копирующих конструкторах?
Имеет ли смысл введение ключевого слова explicit в конструктор с заголовком CSomeClass(size_t m, size_t n = 0) ? Обоснуйте ответ.
Когда имеет смысл определение класса с ключом union? Дайте пример.
В каком случае функция с модификатором const может изменить компонентные данные объекта?
В каких случаях следует объявлять компонентные функции класса константными? Обоснуйте ответ.
Почему статические компонентные функции не могут иметь модификаторов const, volatile и const volatile? Обоснуйте ответ.
Какой вид принимает определение указателя this в зависимости от спецификаторов компонентной функции const, volatile и const volatile?
Задачи
С
проектировать
класс, описывающий конечное множество
натуральных чисел. Включить в класс
функции для добавления элементов в
множество, удаления элементов из
множества, проверки принадлежности
элемента множеству, сравнения множеств.
Предусмотреть также функции для
объединения, пересечения и разности
множеств. Показать использование
класса множества в программе.Разработать класс, описывающий библиографическую карточку. Ввести в класс компоненты для представления вида издания (книга, журнал, сборник и т.д.), вида публикации (статья, тезисы, техническое описание и т.п.), выходных данных (место и год издания, число страниц), названия и фамилий авторов. Создать несколько объектов класса. Показать как с ними можно работать.
Написать определение и реализацию класса, представляющего сотрудника некоторой организации. Класс должен содержать компоненты для хранения фамилии и инициалов сотрудника, его табельного номера, даты рождения, занимаемой должности, номера отдела, оклада. Также в классе должны быть функции, имитирующие ключевые аспекты работы с данными о сотруднике.
Разработать класс для представления виртуальной записной книжки. Включить в класс функции для открытия и закрытия записной книжки, перелистывания страниц книжки, записи текста, вырывания страниц. Показать примеры использования класса в проекте.
