лекции (2007), страница 14

2019-09-19СтудИзба

Описание файла

Документ из архива "лекции (2007)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "лекции (2007)"

Текст 14 страницы из документа "лекции (2007)"

istream ostream

\ /

iostream

Если просто унаследовать istream и ostream от ios, а потом унаследовать от них iostream, то в iostream будет два поля fd (для файлового дескриптора), которые будут использоваться раздельно. Это неправильно, необходим именно один файловый дескриптор и на чтение, и на запись. В связи с этим введёно понятие виртуального наследования:

class ios {...};

class istream : virtual public ios {...}

class ostream : virtual public ios {...}

class iostream : public istream, public ostream {...}

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

В языках C# и Java множественное наследование поддерживается ограниченно: поддерживается наследование от одного произвольного класса и нескольких интерфейсов. Таким образам, наследование по данным в этих языках может быть только единичным.

5.2. Механизмы динамической идентификации типов (RTTI)

RTTI - RunTime Type

- Information

- Identification

Как уже говорилось ранее, объекты ссылочных типов помимо статического типа имеют ещё и динамический тип. Вернёмся к примеру с графическим редактором и предположим, что необходимо перерисовать некоторый набор фигур разных видов. Таким образом, функция отрисовки на вход получает некоторую коллекцию объектов разных типов и по очереди их отрисовывает, причём все эти объекты должны быть фигурами (то есть типы, производные от "Figure"). Но что будет, если в коллекцию случайно попадёт элемент, не являющийся фигурой? Поскольку это никак не контролируется, в программе произойдёт ошибка. Таким образом, иногда встречаются ситуации, когда необходимо по ходу программы уметь определять динамический тип объектов (зачастую в целях безопасности). Поэтому практически во всех современных ЯП реализованы механизмы динамической идентификации типов.

Минимальный механизм реализован в языке Oberon; он состоит из трёх частей:

1) Проверка типа - это механизм, позволяющий как бы "сравнить" два типа. В Oberon проверка типа имеет вид "t is T" (объект t должен обладать динамическим типом); это логическое выражение, которое даст истину, если объект t в качестве динамического типа имеет тип T или производный от T, и ложь в противном случае. Проверка динамического типа будет выглядеть следующим образом:

IF t IS T THEN

...

ELSE

...

END;

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

TYPE T = RECORD

i : INTEGER;

END;

TYPE T1 = RECORD

j : INTEGER;

END;

PROCEDURE P(VAR X : T);

...

BEGIN

...

X(T1).j;

...

END;

Здесь выражение "X(T1)" - это страж типа. То есть, если X имеет тип T или производный от него, то произведётся безопасное преобразование типа и появится доступ к полю j, иначе будет возбуждено исключение. Таким образом, часто проверку и преобразование типов осуществляют следующим образом:

PROCEDURE DRAW (VAR F : Figure)

BEGIN

IF F IS Line THEN

DrawLine(F(Line))

ELSIF F IS Point THEN

DrawPoint(F(Point))

END;

END;

Но это неэффективный вариант - получается, что проверка динамического типа производится второй раз при каждом обращении к объекту. Для оптимизации таких случаев предназначена ещё одна конструкция языка - групповой страж типа.

3) Групповой страж типа - развитие идеи обычного стража типа. Проверка производится один раз, и если она проходит, то в данном блоке больше проверок не производится. Это немного напоминает присоединение в языке Pascal или Modula-2, синтаксис следующий:

WITH X : T DO

...

END;

В рассматриваемом примере процедуру перерисовки можно переписать следующим образом:

PROCEDURE DRAW (VAR F : Figure)

BEGIN

IF F IS Line THEN

WITH F : Line DO

DrawLine(F)

END;

ELSIF F IS Point THEN

WITH F : Point DO

DrawPoint(F)

END;

END;

END;

Хотя в данном примере использование группового стража типа не даёт выигрыша в производительности (всё равно будет производиться две проверки), он бывает удобен, если производится много обращений к объекту.

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

Для простой проверки типа в Delphi используется конструкция "t is T", в Java - "t instanceof T". В Java и C# есть аналоги стража типа: в Java - "T(t)", в C# - "(T)t" (то есть преобразования типов контролируемые). В Delphi же можно производить как контролируемое, так и неконтролируемое динамическое преобразование типов:

1) Контролируемое:

e := t as T;

2) Неконтролируемое:

e := T(t);

Кроме того, в Delphi можно организовать аналог группового стража типа, используя следующую конструкцию:

with t as T do

begin

...

end;

Как уже говорилось ранее, в языках C#, Java и Delphi присутствует дерево типов; другими словами, в этих языках есть базисный класс, называемый Object или TObject. В этом классе могут содержаться дополнительные средства выдачи информации о типе. Более того, к языкам C# и Java применимо понятие "рефлексии" - оно означает, что вся информация о типе содержится в оттранслированном коде и также может использоваться.

Наконец, рассмотрим механизм динамической идентификации типов в языке C++. Здесь условия на тип для произведения идентификации несколько строже: объект класса не только должен обладать динамическим типом (то есть быть указателем или ссылкой), но этот класс также должен иметь хотя бы один виртуальный метод (это требование связано с тем, что у класса должна существовать ТВМ, содержащая необходимую информацию о нём). В общем-то, это не ослабляет механизм RTTI, поскольку именно для классов с виртуальными методами и нужна проверка.

1) Динамическая идентификация типов в C++ производится с помощью конструкции "dynamic_cast <T> (e)". Она одновременно работает и как проверка типа, и как страж типа: если преобразование возможно, то dynamic_cast выдаст преобразованный указатель или ссылку; если это невозможно, то вместо указателя будет выдан NULL, а в случае со ссылкой будет возбуждено исключение "bad_cast".

2) Для ссылок и указателей существует и небезопасное преобразование - "static_cast". Фактически, "static_cast <T> (e)" означает тоже самое, что и "(T)e".

3) Преобразование "reinterpret_cast" позволяет приводить друг к другу несовместимые типы. Контроль, естественно, не осуществляется.

4) Наконец, преобразование "const_cast" позволяет насильно снять константность. Это может быть полезно, если, например, есть константная ссылка на динамический объект.

Кроме преобразований, для получения информации о типе в языке C++ можно использовать специальный псевдокласс type_info и псевдофункцию typeid(e), которая возвращает ссылку на type_info для динамического типа выражения e. Принадлежность объекта конкретному типу можно проверить сравнением ссылок, выдаваемых typeid(): "typeid(t)==typeid(T)".

Глава 6. Статическая параметризация.

Статическая параметризация означает, что связывание параметров (где бы то ни было, в разных языках реализовано по-разному) будет происходить не динамически, а ещё на этапе трансляции. Такая схема часто бывает удобна: например, статическая параметризация типов позволяет избежать накладных расходов на динамическую идентификацию типов. Более того, параметризовывать можно не только типы, но и любые объекты данных (в том числе функции, так как во многих языках есть процедурный тип данных). Простой пример - стек; если необходимо иметь стеки для разных типов элементов и к тому же разной длины, то, используя механизм статической параметризации, можно описать стек, используя пока неизвестный тип объектов и длину стека в виде формальных параметров, а затем при создании каждого нового экземпляра стека указывать тот конкретный тип элементов и ту его длину, которые в данный момент необходимы.

Статическая параметризация появилась в языках программирования достаточно давно - начиная со стандарта Ada-83. В языке C++ она появилась только в начале 90-х годов в виде механизма шаблонов. Как уже было сказано, Бьёрн Страуструп думал о включении шаблонов в C++ ещё в середине 80-х годов, но тогда предпочёл реализовать множественное наследование. В своей книге "Дизайн и эволюция языка С++" Страуструп признаёт это решение одной из немногих своих ошибок. Дело в том, что из-за позднего введения в язык шаблонов позже появилась и библиотека стандартных шаблонов STL, которая только сравнительно недавно завоевала достаточную популярность. Наконец, в языках C# и Java статическая параметризация появилась только в 2004 и 2005 годах соответственно, в виде родовых классов и методов.

Итак, начнём рассмотрение статической параметризации с языка Ada. Для этого механизма в языке было введено новое ключевое слово - "generic"; genegic-модуль называют также "родовым модулем". Для примера возьмём всё тот же стек:

generic

type El is private;

SIZE : integer;

package G_STACKS is

type Stack is private;

procedure Push (S : in out Stack; X : in El);

procedure Pop (S : in out Stack; X : out El);

...

end G_STACKS;

package body G_STACKS is

procedure Pop (S : in out Stack ; X : out T) is ...

procedure Push (S : in out Stack ; X : in T) is ...

private

type Stack is record

body ; array (1..SIZE) of El;

top : integer := 1;

end record;

end G_STACKS;

Здесь используются два параметра - тип элементов стека и длина стека. Соответственно, для создания нового экземпляра стека необходимо создать новый пакет, определив эти два параметра:

package InitStack128 is

new G_STACKS(integer, 128);

Несомненный плюс такого подхода - простота. Но за нёё приходится расплачиваться большим объёмом кода при решении сравнительно небольших задач. Кроме того, часто вриходится вводить большее количество родовых параметра, чем это необходимо. Пример - написание функции сортировки для произвольного типа данных:

generic

type El is private;

type INDEX is range <>;

type ARR is array (INDEX range <>) of El;

with function "<"(X, Y : El) return boolean;

procedure G_SORT(A: in out ARR; L,R : INDEX);

procedure G_SORT(A: in out ARR; L,R : INDEX) is

begin

...

end;

...

private Comp(S1, S2 : String) with function "<" (X, Y : El) return boolean is

begin

...

end;

...

procedure SSort is new G_SORT(String, AS, integer, Comp);

В языке Ada существует огромное разнообразие типов формальных параметров в родовых модулях:

type T is private; -- любой тип с операцией присваивания

type A is array (T1) of E; -- любой массив с индексом типа T1 и элементами типа E (I и E могут быть формальными параметрами)

type IND is range <>; -- любой знаковый целый тип

type I is digits <>; -- любой тип с плавающей точкой

...

Перейдём к рассмотрению средства статической параметризации в языке C++ - механизму шаблонов. Принцип действия тот же самый, синтаксис достаточно простой:

template <список аргументов>

объявление класса или функции;

В C++ есть только три вида формальных параметров: тип, функция или объект данных. Шаблонными могут быть функции и классы. Вот как, например, будет выглядеть шаблонный класс "стек":

template <class T, int size>

class Stack

{

T body[size];

int top;

public:

Stack() { top = 0;}

void Push(T X) { body[top++] = X;}

...

}

Соответственно, создать экземпляр стека можно следующим образом:

Stack <int, 128> S1;

Stack <int, 64*2> S2;

Можно задавать формальные параметры по умолчанию; например, в библиотеке стандартных шаблонов STL при создании контейнеров, как правило, можно не указывать распределитель памяти - аллокатор, тогда будет использоваться стандартный. Например, так выглядит спецификация шаблона для класса vector:

template <class T, class Allocator - allocator<T>> class vector;

В языках C# и Java недавно были введены так называемые родовые классы и методы ("generics"). Синтаксис следующий:

class X <T> {...}

class Y <T> {...}

interface Y <T> {...}

void f <T> (T i) {...}

При этом в Java в качестве формальных параметров могут выступать только классы, в C# параметрами могут быть и типы. Если использовать родовые классы и методы вкупе с наследованием, то получается очень мощный механизм.

Для вас трудились: zvoice, twinka & DiMan

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5301
Авторов
на СтудИзбе
416
Средний доход
с одного платного файла
Обучение Подробнее