- •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
Value_type class_id::function_id(parameters) {statements}
Оно очень похоже на обычное определение функции (есть список параметров parameters, операторы statements, тип значения value_type), но включает полное квалифицированное имя функции class_id::function_id, где :: – операция уточнения контекста.
Если компонентная функция определяется в теле класса, то она может быть реализована как inline-функция. Тело такой функции будет неявно вставляться компилятором во все точки ее вызова. Не всякая функция, определенная в теле класса, будет подставляемой. Подставляемыми обычно делаются только небольшие функции, например, конструкторы или другие функции инициализации, которые не содержат циклов и рекурсий. Подстановку функции можно обеспечить и при ее внешнем определении. Однако в этом случае в ее заголовке перед типом возвращаемого значения следует указать спецификатор inline. Следует отметить, что inline – это только «рекомендация» компилятору выполнить подстановку функции, которая может быть игнорирована.
Оставим более подробное обсуждение элементов определения класса и обратимся к примеру. Ниже дано простейшее определение класса. Класс моделирует понятие «точка на экране дисплея». Естественно, он пока весьма далек от «идеала», но тем не менее будет очень полезен для иллюстрации сути объектного подхода.
class CPoint
{
public: // интерфейс класса
CPoint(int x, int y);
int GetX();
int GetY();
void Show();
void Hide();
bool IsVisible();
void MoveTo(int x, int y);
private: // реализация класса
int __x, __y;
bool __visible;
};
Ниже, для примера, представлены определения функций CPoint::IsVisible и CPoint::MoveTo (определения функций отображения и стирания точки намеренно не даются, так как сам процесс вывода точки сильно зависит от контекста, в котором работает объект).
inline bool CPoint::IsVisible()
{
return __visible;
};
void CPoint::MoveTo(int x, int y)
{
Hide();
__x = x;
__y = y;
Show();
};
Каждая точка – объект класса CPoint – имеет 3 свойства: координату по оси X (компонент __x), координату по оси Y (компонент __y) и признак видимости (__visible). В верхней части определения записаны декларации функций, которые характеризуют возможности наших точек. Например, функции GetX и GetY возвращают соответствующие текущие координаты точки, а функция MoveTo передвигает точку в нужное место на экране.
Определение класса CPoint начинается служебным словом class. Слово class делает все компоненты класса недоступными извне, о чем уже говорилось ранее. Поскольку такой «полностью закрытый» класс вряд ли имеет ценность (получается точка, которая «ничего не умеет»), часть его компонент все же сделана доступной. Для этого было использовано ключевое слово public. Все, что следует за словом public до конца определения класса или до другого слова управления доступностью, считается «видимой» частью класса и называется его интерфейсом. Все, что следует за словом private, вновь недоступно извне. Это реализация класса. В определении класса есть декларация функции, имя которой совпадает с именем класса. Это специальная функция, которая служит для инициализации объектов класса при их создании. Называется она конструктором (более подробно конструкторы будут рассмотрены ниже).
Вообще, в С++ программист имеет три способа управлять доступностью компонент класса и, соответственно, влиять на уровень инкапсуляции. Первый предусматривает использование спецификаторов struct, class и union при определении класса, о которых мы уже говорили выше. В зависимости от используемого спецификатора меняется доступность компонент класса. Если класс определяется как struct, то все его компоненты считаются общедоступными (уровень инкапсуляции минимальный) и к ним можно обращаться извне. Если класс определен с ключом class (как класс CPoint выше), то все его компоненты скрыты (степень инкапсуляции максимальна). При использовании union уровень инкапсуляции такой же, как и у struct, но, в отличие от struct, только один компонент данных активен в каждый момент времени (компоненты совмещены в одной и той же области памяти).
Второй способ отличается тем, что действует не интегрально, на весь класс, а выборочно на требуемые компоненты. Он использует три спецификатора доступности компонент: public, protected и private. Эти спецификаторы могут появляться в любом месте определения класса произвольное число раз в любых сочетаниях. После спецификатора ставится двоеточие. Спецификатор public делает компоненты доступными извне, private, напротив, скрывает компоненты, а protected открывает компоненты только для наследников текущего класса (данный спецификатор подробно будет рассмотрен далее при изучении механизма наследования). Действие спецификатора распространяется от следующего за ним символа двоеточиЯ до следующего спецификатора или до конца определения класса, если данный спецификатор последний.
Третий способ управления доступностью компонент связан с дружественными функциями и классами и будет изучаться в дальнейшем.
В качестве примеров ниже даны определения классов CDate (представление календарных дат) и mod24 (число по модулю 24), где использованы разные ключи и спецификаторы.
class CDate // дата текущего года
{
public:
CDate(int d = 1, int m = 1); // конструктор
int difference(const CDate & date); // разность дат
private:
int __day, __month; // день и месяц
};
struct mod24 // число по модулю 24
{
mod24(int x = 0) // конструктор
{
t = x % 24;
if (t < 0) t += 24;
}
int getvalue() { return t; } // получить число
private:
int t; // t = 0, 1, 2, ..., 23
};
1.3. Создание и уничтожение объектов. Конструкторы и деструкторы
После того, как определение класса задано, можно формировать (определять) локальные, статические и динамические объекты этого класса. Каждый объект – это, упрощенно говоря, участок памяти, где размещены значения данных объекта. Он имеет ту же структуру данных, что определяется классом, но ее значения у разных объектов могут отличаться (набор этих значений называют состоянием объекта). Объект может вызвать функцию, объявленную в теле своего класса; таким образом проявляется определенный аспект поведения объекта.
Ниже даны различные варианты формирования объектов нашего класса CPoint: