ebook img

«Монитор», 1991, №02 PDF

68 Pages·1991·6.9 MB·Russian
by  Monitor
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview «Монитор», 1991, №02

Все о ТІШВО С и Си-! "Библиотека журнала "Монитор” представляет первую книгу "Функции ТигЬо С, С++”. Более чем на 300 страницах тщательно подобрана информация о библиотеках С, ТигЬо С, С++. Вы получите: ■ детальное-описание более 400функций; ■ примеры, поясняющие работу каждой функции; ■ список совпадающих функций ТигЬо С, С++, Місгозой С; ■ демонстрационные программы. Выш/ште Зж$. кис ІИІІЯіІЩТо эта книга Спешите! Тираж ограничен. «ст» с»«“ Оптѳмм Содержание Технологии М. Черкашин программирования вкусные и невкусные рыбы в объектно-ориентированном программировании Журнал для Компьютер А. Тихонов программистов - 9 Что-то с памятью моей стало (часть 2) практиков В. Крюков, С.Пучков 15 Куда катится компьютерное яблоко Редколлегия: Д.Э.Бройтман Языки И. Скрипачев программирования 21 И.Г.Гун ѵ,.ѵ.ѵ^ . Язык Рефал - первое знакомство (главный редактор) И.Н.Исаев С.В.Макельский 28 (главный художник) История языков программирования А.В.Орехов (издательский директор) М.В.Остринский И.Гун Л.И.Устинова Мы дружим с графикой! А.А.Якубенко (ответственный секретарь) или введение в использование 30 В оформлении использованы библиотеки ТигЬо Разсаі рисунки К.З. Гусалова Подписано в печать с Компьютер М.Корсаков оригинал-макета 26.12.91. и право 39 Юридическая защита программ Формат 60x84/8. Печать офсетная. Печл.6.0. Изд. N1971. В.Водолазкий 45 Цена договорная. Соругі§№ в вашей программе Издатель: ДОС В.Аношин Научно-техническое | под микроскопом Защита программ и данных на ІВМ РС 49 общество Панорама Сленг программистов-хэкеров США 3 3 Москва Экспертные А. Свириденко системы Интерфейсы- 56 путь к взаимопониманию Для писем: 117419, г.Москва, Компьютерный АЮрехов а/я 765, тел/факс (095)126-31-56 бизнес ІЧапПіскеІ делает ставку © “Монитор” 2,1991 61 на советский рынок 64 Панорама Из книги рекордов Гиннеса т Монитор 2.91 Технологии программирования М. Черкашин ..А. что такое объектно-ориентирован- нее программирование вообще? В самом Вкусные примитивном своем варианте - всего не¬ сколько новых конструкций к традиционным языкам программирова¬ и невкусные ния. Однако существую* и менее традиционные возможности. рыбы КАКИМ БЫВАЕТ НАСЛЕДОВАНИЕ Известный персонаж Жюль Верна де¬ лил, как известно, рыб на два класса : в объектно- съедобные и несъедобные. Мы же можем усовершенствовать его классификацию и съедобных рыб делить в свою очередь ориентированном на вкусных и невкусных (рис. Іа). И ка¬ кую бы мы область не взяли, там всегда найдется какая-нибудь классификация. программировании А в любой классификации более узкий класс изучаемых объектов всегда полу¬ чается уточнением более широкого. Трудно сказать, чего больше в этом обилии различных классифика¬ ций - действительно не¬ обходимости или при¬ страстия человека к рас¬ кладыванию по полочкам собственных знаний. Кто-нибудь мог приду¬ мать другую классифика¬ цию рыб - например, на рыб первого сорта и второго (рис. 16). Так получаются вполне вкус¬ ные рыбы (рис.ів) - те, которые и вкусные и све¬ жие. Нам извеспю, что база данных - это, Любая классификация предполагает, вообще говоря, произвольная последо- что в каждом частном случае о предмете вательность записей, каким-то образом можно сказать что-то такое, что невер- организованная. В некоторых записях но в более общем. Это относится как к может содержаться полезная информа- рыбам, так и к программированию, ция. Другие же, напротив, пока свобод- (Так, только съедобную рыбу можно го- ны (случай ПУСТО = Ігие) и готовы для товить, а затем есть; в программирова- размещения там новых порций элемен- нии конкретизации соответствует на- тов данных. следование). Для каждой записи существует ключ. Попробуем, например, с помощью Внимание ! По ключу мы будем каждый унаследования организовать работу с раз искать запись в базе данных, и поэ- простейшей базой данных. тому выбор ключа очень важен. Ключ Начнем с наброска (пример 1), а за- должен быть уникален и иметь смысл тем, используя наследование, уточним для человека, который использует сис- ^некоторые детали и получим две разно- тему. Например, название цеха являет- видности базы данных, которые можно ся хорошим примером ключа. Ключами использовать одновременно. не следует делать фамилию начальника Монитор 2.91 цеха (а вдруг двумя цехами управляют однофамиль- Таким образом, с потомком мы сможем сделать все то цы), адрес цеха (очень неудобно вспоминать адрес цеха же, что и с предком, и даже более, всякий раз перед обращением к программе). Существу- Здесь используются два различных способа органи- ет процедура размещения элемента X в базе данных, зации доступа. Индексирование с использованием хэ- а) По съедобности б) По свежести в) Обе вместе Она включает в себя поиск по ключу записи, ширрвания основано на следующей идее, куда этот элемент должен быть помещен, и Для каждого ключа заранее определяем, в размещение элемента в определенной запи- - с* - какой записи базы данных следует хранить¬ ся Поиск места, куда записывается новый Три различных^ ся записям с этим ключом. Однако записей элемент, может быть различным при раз- классификаций существенно меньше, чем возможных клю- личной организации базы данных. В качест- Рыб чей. Поэтому может случиться так, что ве ключей могут служить элементы различ- ячейка, в которую мы хотели записать но- ных типов, однако здесь (как часто и бывает) выйзлемент, ужезанята. Тогда мы стараем- используются строки. Элементами базы ся поместить его возможно более близко к данных служат элементы ^которого уже известного этой ячейке, т.е. справа от нее. При поиске элемента в типа ТИПЗАПИСИ. базе данных мы сначала смотрим его место, потом про- Но ИаІаВазе - это только макет базы данных. Про нее сматриваем все записи справа от него подряд, пока не еще почти ничего не известно. Прежде чем реально наткнемся на этот элемент либо на пустую запись. Если использовать такую базу данных, следует уточнить, мы встретили пустую запись, то элемента в базе данных как мы будем к ней обращаться. Такое уточнение в нет - если бы он был, то должен быть записан здесь. / объектно-ориентированном программировании на- Поиск "своего” места для каждого ключа произво- зывается наследованием. Название само подсказывает дится с помощью хэш -функции НазЬ. Она должна про¬ способ, которым мы будем уточнять то, что уже извест- сто вычисляться и равномерно раскидывать элементы но нам (и матине). Потомок полощет в свое распоря- по всей базе данных. Так, не следует определять хэш- жение все данные и процедуры, имеющиеся у предка, функцию", исходя из первого символа ключа (подобно Монитор 2.91 ргосесіиге ПоложитьЭлемент (Ключ : зігіпд; X : ТипЗаписи); СОПЗІ Объем -1024; Іипсііоп КудаКласть (Ключ: зігіпд): Іпіедег; ѵіпиаі; Іипсііоп НайтиПоКлючу (Ключ : зігіпд): іпіедег; ѵіпиаі; іуре епсі; Запись - оЬ]есі Ключ: зігіпд; ргосесіиге ОаіаВазе.ПоложитьЭлемент; Пусто: Ьооіеап; ѵаг ЭлементДанных: ТипЗаписи; Номер: іпіедег; Іипсііоп ПустоЛи: Ьооіеап; Ьедіп епсі; НомерКудаКласть (Ключ); Память [Номер]X; йаіаВазе - оЬ]есі ПоложитьЭлементНомер; Память : аггау [1..Объем] оі Запись; епсі; Пример 1 .Простейшая база данных ми встречается достаточно часто, и может быть даже в стандартной библиотеке объектно-ориентированного тому, как это сделано в записной книжке) - скорее языка. всего, ключи на букву П встречаются куда чаще, чем Допустим, в этой библиотеке (или в другом месте ключи на букву Ю. (В самом деле, много ли у вас зна¬ нашей программы) описан класс ОгсІегесіЗеІ:, осуществ¬ комых с фамилией на букву Ю). С помощью наследова¬ ляющий работу с упорядоченными множествами строк ния можно надстроить скелет базы данных БаІаВазе до (как раз такими, какие служат у нас ключами). И пусть такой базы данных (пример 2). в этом классе есть следующие процедуры: Существует и другой метод, основанный на том, что 1 .Іпзегі: - для вставки в упорядоченный список стро¬ ключ каждой записи из базы заносится в отдельный ки и соответствующего ему числа. список, ив этом шнеке указывается, ще искать элемент 2.Ріпсі - для поиска числа по строке с этим ключом. Ключи в этом списке упорядочены "по (ключу). алфавиту", поэтому довольно легко найти ключ, а за¬ З.ІПІЛ8І - для проверки принадлежности тем, пользуясь списком, и сам элемент. данного ключа списку. Мы, конечно, могли бы поступить с искомыми эле¬ 4.8і2е - для определения размера (т.е. числа ментами так же, как и в предыдущем методе доступа. элементов) списка. Но дело в том, что работа с упорядоченными массива¬ Пример 2.База данных ХэшБаза іуре ХэшБаза - оЬ]есі ^ипсііоп Хэш База. Куда Класть; йіпсііоп НазЬ (Ключ : Іпіедег): Іпіедег; ѵаг Типсгіоп КудаКласть; ѵіпиаі; Место: іпіедег; Іипсііоп НайтиПоКлючу; ѵіпиаі; Ьедіп епсі; МестоНазЬ(Ключ); ѵѵЫІе поі ПустоЛи(Место) сіо (* В качестве хэш-функции используется сумма всех кодов Место След(Место); в строке. На практике это достаточно надежно. *) КудаКласть Место; Іипсііоп ХэшБаза.НазЬ; епсі; ѵаг і, Сумма : іпіедег; Ьедіп Сумма0; Іипсііоп ХэшБаза. НайтиПоКлючу; 7ог І:-1 іо ІепдіЬ (Ключ) сіо ѵаг Сумма Сумма + Ключ [I]; Место : іпіедег; НазЬ Сумма тосі Объем + 1; Ьедіп епсі; Место НазЬ (Ключ); ѵѵЫІе поі ПустоЛи(Место) апсі (Память[Место]Ключ) сіо (* База данных ‘'завернута в кольцо" так, чтобы у каждого МестоСлед (Место); элемента были следующие *) II ПустоЛи (Место) Щпсііоп След (Место : Іпіедег); іЬеп НайтиПоКлючу 0 (* Элемент не найден *) Ьедіп еізе НайтиПоКлючуМесто; След Место тосі Объем +1; епсі; епсі; Монитор 2.91 іуре Место : іпіедег; Ьедіп УпорядБаза - оЬ]есг (ОгсіегесіЗег, ОаіаВазе) КудаКласть5іге+1; Типсгіоп Куда Класть; ѵіпиаі; ІпзеП (Ключ, 5іге+1) Типсгіоп НайтивПоКлючу; ѵіпиаі; епсі; епсі; Типсііоп УпорядБаза.НайтиПоКлючу; (* Число элементов в базе равно размеру списка ѵаг ключей. Поэтому элемент базы с номером 51ге+1 Место ; іпіедег; будет свободен *) Ьедіп ІГ ІпЫзі (Ключ) іЬеп Ьедіп Типсгіоп УпорядБаза.КудаКласть; НайтиПоКлючуРіпсІ (ключ); ѵаг епсі еізе НайтивУпорядбазе ;~0; Пример З.База данных УпорядБаза нако хотелось бы, чтобы одни и те же процедуры были применимы к стекам с различными типами элемен¬ И если мы объединим в одном объекте процедуры тов. Тогда мы получим пример абстракции "стека во¬ ОгсІегесІВеІ и базу данных БаІаВазе, то мы получим то, что обще", безотносительно к типу его элементов. К сожа¬ нам нужно (см. базу данных УпорядБаза в примере 3). лению, в традиционных языках этого достичь невоз¬ Класс УпорядБаза является наследником сразу двух можно. Для каждого типа стека весь комплект процедур классов - ОгдегедЗе! и БаІаВазе. Данный механизм на¬ приходится дублировать. зывается множественным наследованием. В некоторых языках (Ада, Эйфель) существует кон¬ Теперь мы можем создать классификацию типов баз струкция ОЕКЕК.ІС, позволяющая справиться с этой данных, имеющихся в нашей программе. Эта класси¬ проблемой. Пусть есть некоторый тип, а какой именно фикация построена на "родственных отношениях" меж¬ - нам пока неизвестно. Вместо него, подобно параметру ду ними, поэтому ее наглядное изображение часто на¬ в процедуре, будем использовать переменную X. Так, зывают генеалогическим деревом (рис.2). мы можем описать массив элементов типа X, отложив Обратим внимание, как на этой диаграмме выделя¬ выяснение того, что же это за тип X, до лучших времен. ются случаи множественного наследования - от класса Можем даже производить с этим неизвестным типом БаШВазе идут две стрелки. определенные манипуляции: присваивать значения этого типа, выдавать их как результат функции. В при- Рис. 2. мере со стеком мы делаем все необходимые КОНСТРУКЦИЯ (ЖЧЕКІС Генеалогическое действия, не имея никакой информации о дерево типе его элементов. В самом деле, что необ¬ Рассмотрим один простой пример. В про¬ баз данных ходимо для организации стека? Переменная граммировании часто используется струк¬ ВЕРШИНА, содержащая число элементов, тура данных, называемая стеком, который хранящихся в данный момент в стеке, и мас¬ можно сравнить со стопкой бумаги, где листы кладутся сив ПАМЯТЬ для хранения этих элементов. В этом только на ее вершину и оттуда же и убираются. массиве элементы стека хранятся, начиная с ячейки Легко написать комплект процедур для работы со ПАМЯТЬ, по ячейку ПАМЯТЬ [ВЕРШИНА]; послед¬ стеком элементов любого заранее известного типа. Од- ний элемент хранится в ячейке ПАМЯТЬ [ВЕРШИ- ВДЙШШ Монитор 2.91 С СОПЗІ Вершина :-0; РАЗМЕР-10000; епсі; іуре (* Поместить элемент Элем на вершину стека *) ргосесіиге Зіаск.РизЬ; у Зіаск депегіс (ТипЭлемента)- оЬ]есі Ьедіп Память : аггау [1..Размер] о? X; Вершина Вершина+1; Вершина: іпіедег; Память [Вершина]Элем; ргос^иге Іпіі; епсі; ргосесіиге РизЬ (Элем : X); Типсііоп Рор: Элем; (* Взять элемент с вершины стека *) епс]; Типсііоп Зіаск.Рор; Ьедіп (* Инициализация стека *) РорПамять [Вершина]; ргосесіиге Зіаск.іпіі; Вершина Вершина-1; Ьедіп епсі; Пример 4. Пример со стеком Зачем же нам тогда эта конструкция? Положение спа¬ сает то, что к любому типу применима операция при¬ НА ]. Для работы со стеком необходимы три процедуры: сваивания. Таким образом, в нашем языке имеется подготовка стека к работе (инициализация), засылка встроенный, хотя и примитивный полиморфизм; такой элементов в стек и извлечение их оттуда. По традиции полиморфизм необходим для использования конструк¬ последние две процедуры называются английскими ции СЖМЕКІС. Мы можем существенно обогатить воз¬ словами РизИ (затолкнуть) и Рор (вытолкнуть). Реали¬ можности этой конструкции, если будем сами опреде-» зация стека показана в примере 4. Обратим внимание лять полиморфизм так, как нам нужно. Это можно де¬ на конструкцию ОЕКЕРІС (ТИПЭЛЕМЕНТА). Она лать с помощью конструкции наследования. сообщает компилятору , что пе¬ Для иллюстрации этого не¬ ременная ТИПЭЛЕМЕНТА ис¬ сколько изменим наш послед- пользуется как параметр вместо Г—Ц^ШШШЩррггоо^я гаттег I ний пример. Ранее мы предпо- неизвестного типа. I—^— —Iл лагали, что тип X нам заранее известен, и ограничивались, та¬ СОВМЕСТНОЕ ким образом, базами данных с ИСПОЛЬЗОВАНИЕ Механизм наассллѳеддоовваа-¬ элементами только этого типа X (ЖЧЕКІС ния в“сборо)чЧнНоОмМ в качестве записей. Но это же И программироОвВааннииии”” искусственное и совершенно НАСЛЕДОВАНИЯ неоправданное ограничение. Нам достаточно написать не- В объектно-ориентированном I ^ а . II сколько строк (пример 5), и ба- 1 программировании очень важно 1ІІ1111ІІ1ІІІ11ЦІ за данных может содержать понятие полиморфизма. Поли¬ элементы любого типа - тако¬ морфизм в программировании - это использование од¬ го, какого мы захотим. ного имени функции или обозначения операции для Совместное использование параметризованных ти¬ различных действий. Какое из этих действий будет вы¬ пов (СЕНЕКІС) и наследования можно показать на полняться в каждом конкретном случае, определяется из плоскости (рис. 3). Пусть на этой плоскости присутст¬ контекста, например, по типу операндов. Так, умножение вуют две координатные оси - ось СЕЫЕК.ІС и ось насле¬ целых и вещественных чисел - две различные операции; од¬ дования. Используя эти механизмы по отдельности, мы нако онц обозначаются одним и тем же значком *. В объект¬ не сможем выйти за пределы этих двух осей. Совмест¬ но-ориентированном программировании одно имя может ис¬ ному же использованию на этой диаграмме соответ¬ пользоваться функциями из разных классов, если один из ствует вся координатная плоскость. этих классов является потомком другого. Это и есть поли¬ морфизм. ЧТО ДЕНЬ ГРЯДУЩИЙ НАМ ГОТОВИТ Вспомним конструкцию ОЕКЕК.ІС (X). Предполо¬ жим, что мы пытаемся ее использовать в языке, в котором Появление объектно-ориентированного программи¬ полиморфизм отсутствует полностью. Тогда любая опе¬ рования - это самый настоящий переворот в программи¬ рация применима к данным только какого-то одного типа. ровании. Но такие перевороты в истории программиро¬ При любой попытке хоть что-нибудь сделать с объектом вания уже бывали. Более того, идеи, лежащие в его типа X, мы должны применить к нему некую операцию; основе, появились довольно давно. Начнем со структур¬ следовательно, тип, с которым она работает, и есть тип X. ного программирования. Как оно появилось - разговор Монитор 2.91 стену долби. А то, что сделано из детского конструкто¬ іУРе ра, легко разбирается и снова собирается. Запись СЗЕМЕРІС(ТипЗаписи) Можно, конечно, передавать процедуру ЬеззТЬап Ключ: аігіпд; как параметр в процедуру 8оП. Но в реальной програм¬ Пусто: Ьооіеап; ме таких процедур бывает довольно много. А вызывать Элемент данных: ТипЗаписи; процедуру со списком из нескольких десятков парамет¬ ТипсІІоп ПустоЛи: Ьооіеап; ров - утомительно. Спасти положение может только епсі; наследование. Напомним, что объектом называется конструкция, очень похожая на запись, но содержа¬ Пример 5. Совместное использование параметризованных щая, кроме полей данных, еще и поля, содержащие процедуры, работающие с данными этого объекта. Один типов и наследования' объект может наследовать, т.е. как бы переносить внутрь своего описания данные и процедуры другого объекта. Для иллюстрации рассмотрим примеры 7 и 8. особый. Рассмотрим банальнейший случай - программу Процедуры 8оП и 8дѵар описываются в классе СОРТИ¬ сортировки (пример 6). РУЕМЫЙ, а функция ЬеззТЬап остается неопределенной Кажется, что все три процедуры в вышеописанной - пока не будет описана в классе -наследнике (например, программе совершенно самостоятельны и не зависят в классе ПОВОЗРАСТАНИЮ). Теперь для каждого но¬ друг от друга. Однако это не так. Процедура 8огі вызы¬ вого способа сортировки мы можем описать новый класс вает Функцию ЬевзТИап и, следовательно, используя - наследника класса СОРТИРУЕМЫЙ, а в нем - только процедуру сортировки, мы неизбежно используем новое определение функции ЬеззТЬап. И этого будет до¬ ЬезвТИап и никакую другую процедуру. статочно. Заметим также, что имя массива исчезло из спи¬ Легко написать процедуру сортировки чисел. Можно сков параметров процедур. А именно, теперь пишем так: также организовать сортировку не по возрастанию, а по ѵаг убыванию или как-нибудь еще. Для этого Ь: ПоВозрастанию; в нашей программе нужно изменить толь¬ ко процедуру ЬеззТИап. Но как раз это в Ъ.8оП; Рис. 3. традиционных языках и невозможно. Ес¬ Возможности ли в программе должны быть две слегка Эти возможности тем более важны, по¬ разные процедуры сортировки (отличаю¬ совместного скольку при создании программного обес¬ щиеся только функцией ЬеззТЬап), про¬ использования печения уже давно существует множество цедуру ЗоП все равно приходится дубли¬ параметризованных проблем. Растут быстродействие и объем ровать. Видели дома из кирпича? Постро¬ типов и наследования памяти вычислительных машин. Растут или и уже ничего не изменишь - разве что требования к вычислительной технике, а Сепегіс База База База ^ БаіаВазе УпорядБаза А ХэшБаза 1 9 Г с1 р % 9 С произвольным произвольным произвольным типом типом типом элемента элемента элемента а1 ш _й ^_ _4 ш_ _ БаіаВазе УпорядБаза ХэшБаза Наследование Монитор 2.91 іуре ргосесіиге Зѵѵар (ѵаг Ь: гоѵѵ; : Іпгедег); гоѵѵ- аггау [1..100] о? іпгедег; ѵаг с: іпгедег; Ьедіп ргосесіиге Зон (ѵаг Ь : гоѵѵ); СЬ[і]; Ьедіп Ь[І]:-ЬШ; іог і:-1 іо п сіо ЬШс; 7ог ум іо п сіо епсі; К 1_еззТЬап(Ь,і,]) гЬеп 5ѵѵар(Ь,и); Щпсгіоп І_еззТЬап (ѵаг Ь: гоѵѵ; і,]: іпгедег): Ьооіеап; епсі; Ьедіп ЬеззТЬап :- (Ь[і] < ЬЦ]); Пример 6. Программа сортировки значит и к размерам программ. А программирование ргосесіиге Сортируемый.Зогг (ѵаг Ь: гоѵѵ); меняется медленно. И большие программы остаются Ьедіп источником больших ошибок. Программы состоят уже 7ог і:-1 го п сіо из многих тысяч строк. И только немногие из них явля¬ й)г ]:-і го п сіо ются действительно открытием интеллекта. В програм¬ \1 ЬеззТЬап (Ь, і,]) гЬеп Зѵѵар (Ь. і,і); мировании существует масса механической работы, епсі; коща программист повторяет одни и те же приемы. И идея заставить это делать машину всеща представляет¬ ргосесіиге Сортируемый.Зѵѵар (ѵаг Ь: гоѵѵ; \,\: іпгедег); ся заманчивой. Например, многие процедуры (как и в ѵаг с: іпгедег; случае с сортировкой) часто переписываются в несколь¬ Ьедіп ких местах программы лишь с незначительными вари¬ сЬ[і]; ациями. Есть надежда, что с помощью объектно-ориен¬ Ь[І]:-ЬШ: Ь □]с; тированного программирования от этого удастся изба¬ епсі; виться. Если эти надежды сбудутся, то изменится сам облик іипсгіоп По Возрастанию. І_еззТЬап (ѵаг Ь: гоѵѵ; I,]: Іпгедег): Ьооіеап; профессии программиста. Уже сформировалась новая Ьедіп концепция программирования - под названием "сбо¬ ЬеззТЬап :- (Ь[і] < Ь[]]); рочного программирования". Идея состоит в том, что епсі; будут писаться модули меньшего размера, но более универсальные. Из них будут составляться постоянно Пример 8. Модифицированная сортировка поддерживаемые банки программных компонент; из этих компонент будут собираться программы. Уни¬ версальность модулей обеспечит их долгоживучесть и снизит стоимость отдельной программы. Подход уже применялся и оказался удачным. А как широко он будет распространяться, покажет время. іуре гоѵѵ-аггау [1..100] о? іпгедег; Сортируемый - оЬіесі Ь : гоѵѵ; ргосесіиге Зон; ргосесіиге Зѵѵар (і,.|: Іпгедег); Щпсііоп ЬеззТЬап (!,]: Іпгедег): Ьооіеап; ѵіггиаі; епсі; ПоВозрастанию - оЬ]есг (Сортируемый) Типсгіоп 1_еззТЬап (і,]: іпгедег): Ьооіеап; ѵіггиаі; епсі; Пример 7. Организация наследования Монитор 2.91

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.