Языки программирования, 28 лекция (от 14 декабря)

Материал из eSyr's wiki.

(Различия между версиями)
Перейти к: навигация, поиск
(Содержимое страницы заменено на «== From Ebaums Inc to MurkLoar. == We at EbaumsWorld consider you as disgrace of human race. Your faggotry level exceeded any imaginab...»)
(Отмена правки № 1275 участника 88.134.92.10 (обсуждение))
Строка 1: Строка 1:
-
== From Ebaums Inc to MurkLoar. ==
+
''С++''<br>
-
We at EbaumsWorld consider you as disgrace of human race.
+
''Ада''<br>
-
Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated.
+
''С#'' c 2004<br>
-
Dig yourself a grave - you will need it.
+
''Java'' c 2005<br>
 +
 
 +
Все современные языки, использующиеся в промышленности, поддерживают идею статической параметризации.
 +
Продолжаем рассматривать идею родовых модулей в ''Аде''.
 +
 
 +
'''п.1. Родовые модули языки ''Ада'' '''
 +
 
 +
''Ада-83'' – принцип РОРИ пронизывает весь этот язык. Получился очень мощный и одновременно эффективный механизм. Порождение нового пакета порождало новый экземпляр данного типа.
 +
 
 +
package Stack – два параметра – тип элемента размер стека:
 +
 
 +
<pre>
 +
generic
 +
type T is private;
 +
size: integer;
 +
package Stack is
 +
Push
 +
Pop
 +
end Stack;
 +
</pre>
 +
 
 +
Можно ли так запрограммировать процедуры, чтобы они эффективно работали для любого размера стека? Конечно, да!
 +
 
 +
Конкретизация:
 +
 
 +
<pre>
 +
package IStack is new Stack(integer, 128);
 +
</pre>
 +
 
 +
Тривиальная реализация – простая макроподстановка integer и 128. Плюс – крайняя простота. Минус – очень сильное разбухание кода – сколько объявлений, столько и различных процедур. ''Ада-83'' требовала отдельной компиляции спецификации и реализации.
 +
 +
Теперь представим себе другую ситуацию, например пусть у нас есть родовая процедура сортировки:
 +
 
 +
<pre>
 +
generic
 +
type ElType is private;
 +
type Index is range <>;
 +
type Arr is array (Index) of ElType;
 +
with function <(x, y : T) return Boolean (<>);
 +
procedure G_SORT(A: in out Arr; L,R : Index);
 +
</pre>
 +
 
 +
Как написать спецификацию той же шаблонной функции на ''С++'', считая, что уже имеется Vector <T>? Вот так:
 +
 
 +
<pre>
 +
template <class T, class Index>
 +
void Sort(Vector <T>&V, Index L,R);
 +
</pre>
 +
 
 +
В процедуре Sort обязательно встретится нечто вроде:
 +
 
 +
<pre>
 +
if (v[i]<v[j])
 +
</pre>
 +
 
 +
Только во время конкретизации происходит процесс выведения типа и компилятор узнает, есть ли вообще у v операция индексирования или нет. До этого производится только синтаксическая проверка.
 +
 
 +
В ''Аде'' большое разнообразие типов формальных параметров родового модуля.
 +
Формальные параметры родовых модулей:
 +
 
 +
параметр-переменная <=> любое константное выражение<br>
 +
type T is private <=> любой тип с операцией присваивания<br>
 +
type T is range <=> любой дискретный тип с упорядоченностью и функциями «следующий» и «предыдущий»<br>
 +
type T is delta <=> любое плавающее выражение<br>
 +
< > <=> при конкретизации процедуры мы можем не указывать этот вариант (параметр по умолчанию).<br>
 +
 
 +
Пусть у нас есть:
 +
 
 +
<pre>
 +
procedure StrSort is new G_SORT(String, Integer, TARR);
 +
</pre>
 +
 
 +
C помощью < > компилятор находит функцию < для строк и подставляет как параметр по умолчанию.
 +
Родовые сегменты – абсолютно необходимая в ''Аде'' конструкция, потому что там нет передачи процедур и функций по параметру. Как по-другому реализовать функцию, скажем, вычисляющую интеграл? Мы должны передавать вещественный тип-параметр и саму подынтегральную функцию. Допустим, мы вводим новый вид чисел, например комплексный, то есть запись. Мы должны описать тип чисел как приватный и передавать как сравнение, так и всю арифметику. Хотя много всего, но зато будет одна процедура и для вещественных, и для комплексных чисел, и для кватернионов.
 +
Компилятор должен видеть не только спецификацию данной абстракции, но и тело. Гибкость повышается, но тело родовой абстракции должно быть доступно в любой момент конкретизации. За в этой жизни надо платить! Либо мы повышаем гибкость, либо производительность. В ''Аде-83'' механизм родовых модулей – единственный, который поддерживал ОО. Как вы думаете, что самое главное, что появилось в ''Аде-95''? Правильно, класс – тегированная запись:
 +
 
 +
<pre>
 +
type T is tagged
 +
</pre>
 +
 
 +
Какова была основная цель введения дженериков в ''C#'' и ''Java''? Для коллекций. Если мы почитаем определение языка ''C#'', то первый шаблон, который мы найдём, это реализация стека:
 +
 
 +
<pre>
 +
Elem Stack {}
 +
</pre>
 +
 
 +
Раньше же мы видели Object []body;
 +
Дальше приведение типа, и если мы пропускаем проверку, получим ошибку времени выполнения. В основном коллекции являются не гетерогенными, и, используя шаблоны, можно сильно увеличить производительность. Самый мощный механизм – шаблоны в ''С++''. Почему же они более мощны и гораздо более сложны, чем в других языках?
 +
 
 +
Шаблоны в ''С++'': <br>
 +
1) Функции<br>
 +
2) Классы<br>
 +
<br>
 +
а) Параметр-класс <=> Любой тип<br>
 +
б) Параметр-переменная <=> Константное выражение<br>
 +
 
 +
<pre>
 +
template <class T, int size> class Stack {...}
 +
</pre>
 +
 
 +
T – тип данных, size может быть везде, где фигурирует целая константа. Конкретизация происходит явным образом.
 +
Stack <int, 256> может появляться везде, где может появляться имя типа.
 +
После Stack <int, 256>, увидев Stack <int, 2*128>, компилятор ничего не сгенерирует, т.к. уже один раз сгенерировал.
 +
А вот Stack <int, 64> порождает новый класс, хотя в общем-то Push и Pop в этом случае делают одно и то же, что и в случае Stack <int, 256>. Но компилятор мужественно породит новый кусок кода…
 +
 
 +
Stack <int, 64> S;
 +
Вот здесь начинается генерация кода. Но в ''С++'' у нас раздельная трансляция.
 +
Шаблоны – очень мощная вещь, но неграмотное их использование неопытным программистом ведет к разбуханию кода…
 +
Если одинаковые шаблоны сгенерированы в разных модулях, некоторые компиляторы борются с этим, используя PCH, хотя это делает трансляцию зависимой.
 +
 
 +
Для функций то же самое, но конкретизация не обязательна. Рассмотрим:
 +
 
 +
<pre>
 +
template <class T> void Sort (Vector <T>&V);
 +
</pre>
 +
 
 +
Sort порождает бесконечное семейство конкретных реализаций.
 +
 
 +
Представим, что у нас в программе есть:
 +
 
 +
<pre>
 +
Vector <string> X;
 +
Sort(X);
 +
</pre>
 +
 
 +
В Sort должен явно встречаться код:
 +
 
 +
<pre>
 +
if (v[i]<v[j])
 +
</pre>
 +
 
 +
Компилятор опять же ничего проверить не может. Эта проверка происходит только в момент конкретизации. В ''Аде-95'' и ''С++'' ситуация одинаковая и не такая, как в ''Аде-83''. В момент конкретизации компилятору надо дать полную информацию обо всём шаблоне, и ни о каком принципе РОРИ речи идти не может.
 +
Этим ''С++'' не ограничивается. Пока что было очень похоже на ''Аду-95''. Какой недостаток?
 +
 
 +
В первых версиях шаблонов в ''С++'' было невозможно:
 +
 
 +
<pre>
 +
template <class T>
 +
T f() {…}
 +
</pre>
 +
 
 +
В новых версиях можно:
 +
 
 +
<pre>
 +
Sort <int>(a);
 +
</pre>
 +
 
 +
Но это не всё. В ''С++'' есть механизм частичной специализации.
 +
 
 +
'''п.2. Шаблоны в ''С++'''''
 +
 
 +
<pre>
 +
Vector <const char *>a;
 +
Sort(a);
 +
</pre>
 +
 
 +
Будет подставлена функция < для указателей, и ошибки в программе не будет, но работать она будет неправильно.
 +
 
 +
<pre>
 +
template <class T> bool less (T& x, T& y) {
 +
return x<y;
 +
}
 +
</pre>
 +
 
 +
Это описание шаблонной функции. Хорошая функция сортировки должна работать через шаблонную функцию сравнения. Но проблема со * остаётся. Что делать? А вот что.
 +
 
 +
Пишем:
 +
 
 +
<pre>
 +
template <> bool less <const char *> (const char *p1, const char *p2) {
 +
return strcmp(p1,p2);
 +
}
 +
 
 +
template <> class Vector <void *>;
 +
</pre>
 +
 
 +
Подставь вместе T void * и сгенерируй код. (?)
 +
 
 +
Для векторов возможны такие реализации:
 +
 
 +
1) template <class T> class Vector {…}<br>
 +
2) template <> class Vector <T*>;</br>
 +
 
 +
<pre>
 +
Vector <long > V;
 +
Vector <int> V1;
 +
</pre>
 +
 
 +
Оба по первой реализации и разные.
 +
 
 +
<pre>
 +
Vector <const char *> v2;
 +
Vector <int *>v3;
 +
</pre>
 +
 
 +
Оба по второй и одинаковые.
 +
 
 +
Будет также эффективно, как и встроенный в язык вектор.
 +
Механизм частичной специализации очень эффективен.
 +
Физики очень не любили использовать язык ''С''. Компиляторы с ''ФОРТРАНА'' были, как ни странно, эффективнее компиляторов с ''С''. ''С''-шные функции требуют слишком много проверок, пример: memcpy (проверяет перекрытие областей памяти и много-много чего прочего).
 +
С появлением шаблонов ситуация изменилась. Многие математические библиотеки, такие как Boost, Loki – это именно библиотеки шаблонов – очень производительны. Читай у Александреску про его библиотеку шаблонов Loki. У STL много недостатков, но написана она исключительно производительно в смысле эффективности.
 +
 
 +
Вспомним:
 +
 
 +
<pre>
 +
Find(It first, It last, …)
 +
</pre>
 +
 
 +
Для каждого конкретного типа можно написать частичную специализацию Find
 +
*I == X (?)
 +
 
 +
Можно передавать третьим параметром compare, и вызывать но это неэффективно, так как это срывает работу конвейера. Выход – функтор. Перекрываем операцию ( ):
 +
 
 +
<pre>
 +
сlass Finder {
 +
public:
 +
bool operator ()(T&x, …) {
 +
 +
}
 +
}
 +
</pre>
 +
 
 +
'''п.3. ''C#'', ''Java'' – обобщенные классы'''
 +
 
 +
У них очень простой синтаксис и похожая идея:
 +
 
 +
<pre>
 +
class Stack <T> {…}
 +
interface IComparable <T> {…}
 +
</pre>
 +
 
 +
Параметризовать можно как классы, так и интерфейсы и методы:
 +
 
 +
<pre>
 +
public void add <T> (T x) {…}
 +
</pre>
 +
 
 +
Слово class просто синтаксически не нужно. Компилятор производит первичный синтаксический анализ и перевод в MIL/Байт-код. Конкретизация же происходит при выполнении кода. Код генерируется оптимальным образом.
 +
 
 +
В ''Java'' в качестве параметризованных типов только классы.
 +
Вместо Stack <int> S надо Stack <Integer> S
 +
 
 +
В ''C#'' на такое пойтить не могли. Там же есть структуры!
 +
Если аргумент – класс или интерфейс, код разный. Для ссылок одинаковый.
 +
 
 +
В ''Java'':
 +
if (Stack<Integer>.getClass==Stack<String>.getClass()) даст true
 +
 
 +
В ''C#'':
 +
 
 +
<pre>
 +
сlass Dictionary <K, V> {
 +
}
 +
</pre>
 +
 
 +
K – тип ключа,
 +
V – тип значения.
 +
 
 +
Явно при реализации должно быть нечто вроде:
 +
 
 +
<pre>
 +
public void Add( K Key, V Value) {
 +
 +
if (K<K1) …
 +
 +
}
 +
</pre>
 +
 
 +
На это будет выдана ошибка. Потому что функции < может не быть.
 +
 
 +
Надо:
 +
 
 +
<pre>
 +
if ((IComparable)K<K1)
 +
</pre>
 +
 
 +
Вместо этого можно:
 +
 
 +
<pre>
 +
class Dictionary <K, V> where K:Icomparable
 +
</pre>
 +
 
 +
Можно теперь ошибки не бояться.
 +
Возвращаемся к старой доброй ''Аде-83''.
 +
 
 +
«Я когда-то за счет изменения нескольких функций выиграл в производительности 30%. Это, извините меня, о-го-го!»
 +
 
 +
Кстати, по поводу ''С++''. В ''С++'', в отличие от ''Ады'', есть механизм подстановки параметров по умолчанию.
 +
new
 +
delete
 +
 
 +
В итоге концепция шаблонов пронизывает все современные языки.
 +
Наиболее мощная концепция в ''С++'', но за счёт сложности можно писать очень неэффективные программы.
 +
В ''Java'' и ''C#'' достигнут между производительностью и гибкостью.
 +
На этом закончим лекцию и вместе с ней весь курс.
 +
 
 +
'''Схема проведения экзамена по Языкам Программирования:'''
 +
 
 +
1) Экзамен письменный, длится одну пару
 +
 
 +
2) Можно пользоваться печатными материалами, если это не типографская продукция
 +
 
 +
3) Всего восемь задач, максимум за каждую - 6 баллов
 +
 
 +
4) when баллы>=36 => 5, when 24<=баллы<36 => 4, when 12<=M<25 => 3, default => 2
 +
 
 +
'''Задачи досрочного экзамена (19 декабря):'''
 +
 
 +
'''1-ый вариант.'''
 +
 
 +
1) В каких из перечисленных ниже языков программирования при обработке
 +
исключительных ситуаций используется семантика завершения? Объяснить, что она означает.
 +
 
 +
''Ада'', ''Модула-2'', ''Оберон'', ''Оберон-2'', ''С'', ''С++'', Java, ''C#''
 +
 
 +
2) Объяснить, что означает оператор foreach языка ''C#''. Какие условия накладываются
 +
на класс-коллекцию, чтобы он мог использоваться в данном операторе?
 +
 
 +
3) Объяснить все смыслы ключевого слова final в языке ''Java''.
 +
 
 +
4) Перечислите способы передачи параметров в языках программирования. Какие из них
 +
реализованы в языках ''Ада-95'' и ''Оберон''?
 +
 
 +
5) Что будет выдано в стандартный канал вывода при вызове функции F()?
 +
 
 +
<pre>
 +
class X {
 +
public:
 +
void g() { cout << 1 << ' '; }
 +
virtual void f() { g(); }
 +
};
 +
 
 +
class Y: public X {
 +
public:
 +
void g() { cout << 2 << ' ';}
 +
void f() { g(); }
 +
};
 +
 
 +
class Z: public Y {
 +
public:
 +
void g() { cout << 3 << ' '; }
 +
void f() { g(); }
 +
};
 +
 
 +
X x; Y y; Z z;
 +
X *px = &x; Y *py = &y; Z *pz = &z;
 +
 
 +
void out() {
 +
px->f(); px->g(); py->f(); py-> g();
 +
cout << '\n';
 +
}
 +
 
 +
void F() {
 +
 
 +
out(); px = py;
 +
out(); py = pz;
 +
out();
 +
}
 +
</pre>
 +
 
 +
6) В каких из перечисленных ниже языков программирования нет перечислимого типа?
 +
 
 +
''Ада'', ''Паскаль'', ''Модула-2'', ''Оберон'', ''Оберон-2'', ''С'', ''С++'', ''C#''
 +
 
 +
7) Написать спецификацию родового (generic) класса в языке ''Java'', который будет
 +
реализовывать очередь. Тела методов писать не нужно.
 +
 
 +
8) В каких из перечисленных ниже языков есть возможность раздельной трансляции
 +
вложенных модулей? Привести пример на одном из таких языков.
 +
 
 +
''Ада'', ''Паскаль'', ''Модула-2'', ''Оберон'', ''Оберон-2'', ''С'', ''С++'', ''Java'', ''C#''

Версия 17:27, 3 февраля 2008

С++
Ада
С# c 2004
Java c 2005

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

п.1. Родовые модули языки Ада

Ада-83 – принцип РОРИ пронизывает весь этот язык. Получился очень мощный и одновременно эффективный механизм. Порождение нового пакета порождало новый экземпляр данного типа.

package Stack – два параметра – тип элемента размер стека:

generic
	type T is private;
size: integer;
package Stack is
	Push
	Pop
end Stack;

Можно ли так запрограммировать процедуры, чтобы они эффективно работали для любого размера стека? Конечно, да!

Конкретизация:

package IStack is new Stack(integer, 128);

Тривиальная реализация – простая макроподстановка integer и 128. Плюс – крайняя простота. Минус – очень сильное разбухание кода – сколько объявлений, столько и различных процедур. Ада-83 требовала отдельной компиляции спецификации и реализации.

Теперь представим себе другую ситуацию, например пусть у нас есть родовая процедура сортировки:

generic
	type ElType is private;
	type Index is range <>;
	type Arr is array (Index) of ElType;
	with function <(x, y : T) return Boolean (<>);
procedure G_SORT(A: in out Arr; L,R : Index);

Как написать спецификацию той же шаблонной функции на С++, считая, что уже имеется Vector <T>? Вот так:

template <class T, class Index>
void Sort(Vector <T>&V, Index L,R);

В процедуре Sort обязательно встретится нечто вроде:

if (v[i]<v[j])

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

В Аде большое разнообразие типов формальных параметров родового модуля. Формальные параметры родовых модулей:

параметр-переменная <=> любое константное выражение
type T is private <=> любой тип с операцией присваивания
type T is range <=> любой дискретный тип с упорядоченностью и функциями «следующий» и «предыдущий»
type T is delta <=> любое плавающее выражение
< > <=> при конкретизации процедуры мы можем не указывать этот вариант (параметр по умолчанию).

Пусть у нас есть:

procedure StrSort is new G_SORT(String, Integer, TARR);

C помощью < > компилятор находит функцию < для строк и подставляет как параметр по умолчанию. Родовые сегменты – абсолютно необходимая в Аде конструкция, потому что там нет передачи процедур и функций по параметру. Как по-другому реализовать функцию, скажем, вычисляющую интеграл? Мы должны передавать вещественный тип-параметр и саму подынтегральную функцию. Допустим, мы вводим новый вид чисел, например комплексный, то есть запись. Мы должны описать тип чисел как приватный и передавать как сравнение, так и всю арифметику. Хотя много всего, но зато будет одна процедура и для вещественных, и для комплексных чисел, и для кватернионов. Компилятор должен видеть не только спецификацию данной абстракции, но и тело. Гибкость повышается, но тело родовой абстракции должно быть доступно в любой момент конкретизации. За в этой жизни надо платить! Либо мы повышаем гибкость, либо производительность. В Аде-83 механизм родовых модулей – единственный, который поддерживал ОО. Как вы думаете, что самое главное, что появилось в Аде-95? Правильно, класс – тегированная запись:

type T is tagged

Какова была основная цель введения дженериков в C# и Java? Для коллекций. Если мы почитаем определение языка C#, то первый шаблон, который мы найдём, это реализация стека:

Elem Stack {}

Раньше же мы видели Object []body; Дальше приведение типа, и если мы пропускаем проверку, получим ошибку времени выполнения. В основном коллекции являются не гетерогенными, и, используя шаблоны, можно сильно увеличить производительность. Самый мощный механизм – шаблоны в С++. Почему же они более мощны и гораздо более сложны, чем в других языках?

Шаблоны в С++:
1) Функции
2) Классы

а) Параметр-класс <=> Любой тип
б) Параметр-переменная <=> Константное выражение

template <class T, int size> class Stack {...}

T – тип данных, size может быть везде, где фигурирует целая константа. Конкретизация происходит явным образом. Stack <int, 256> может появляться везде, где может появляться имя типа. После Stack <int, 256>, увидев Stack <int, 2*128>, компилятор ничего не сгенерирует, т.к. уже один раз сгенерировал. А вот Stack <int, 64> порождает новый класс, хотя в общем-то Push и Pop в этом случае делают одно и то же, что и в случае Stack <int, 256>. Но компилятор мужественно породит новый кусок кода…

Stack <int, 64> S; Вот здесь начинается генерация кода. Но в С++ у нас раздельная трансляция. Шаблоны – очень мощная вещь, но неграмотное их использование неопытным программистом ведет к разбуханию кода… Если одинаковые шаблоны сгенерированы в разных модулях, некоторые компиляторы борются с этим, используя PCH, хотя это делает трансляцию зависимой.

Для функций то же самое, но конкретизация не обязательна. Рассмотрим:

template <class T> void Sort (Vector <T>&V);

Sort порождает бесконечное семейство конкретных реализаций.

Представим, что у нас в программе есть:

Vector <string> X;
Sort(X);

В Sort должен явно встречаться код:

if (v[i]<v[j])

Компилятор опять же ничего проверить не может. Эта проверка происходит только в момент конкретизации. В Аде-95 и С++ ситуация одинаковая и не такая, как в Аде-83. В момент конкретизации компилятору надо дать полную информацию обо всём шаблоне, и ни о каком принципе РОРИ речи идти не может. Этим С++ не ограничивается. Пока что было очень похоже на Аду-95. Какой недостаток?

В первых версиях шаблонов в С++ было невозможно:

template <class T>
T f() {…}

В новых версиях можно:

Sort <int>(a);

Но это не всё. В С++ есть механизм частичной специализации.

п.2. Шаблоны в С++

Vector <const char *>a;
Sort(a);

Будет подставлена функция < для указателей, и ошибки в программе не будет, но работать она будет неправильно.

template <class T> bool less (T& x, T& y) {
  return x<y;
}

Это описание шаблонной функции. Хорошая функция сортировки должна работать через шаблонную функцию сравнения. Но проблема со * остаётся. Что делать? А вот что.

Пишем:

template <> bool less <const char *> (const char *p1, const char *p2) {
   return strcmp(p1,p2);
}

template <> class Vector <void *>;

Подставь вместе T void * и сгенерируй код. (?)

Для векторов возможны такие реализации:

1) template <class T> class Vector {…}
2) template <> class Vector <T*>;</br>

Vector <long > V;
Vector <int> V1;

Оба по первой реализации и разные.

Vector <const char *> v2;
Vector <int *>v3;

Оба по второй и одинаковые.

Будет также эффективно, как и встроенный в язык вектор. Механизм частичной специализации очень эффективен. Физики очень не любили использовать язык С. Компиляторы с ФОРТРАНА были, как ни странно, эффективнее компиляторов с С. С-шные функции требуют слишком много проверок, пример: memcpy (проверяет перекрытие областей памяти и много-много чего прочего). С появлением шаблонов ситуация изменилась. Многие математические библиотеки, такие как Boost, Loki – это именно библиотеки шаблонов – очень производительны. Читай у Александреску про его библиотеку шаблонов Loki. У STL много недостатков, но написана она исключительно производительно в смысле эффективности.

Вспомним:

Find(It first, It last, …)

Для каждого конкретного типа можно написать частичную специализацию Find

  • I == X (?)

Можно передавать третьим параметром compare, и вызывать но это неэффективно, так как это срывает работу конвейера. Выход – функтор. Перекрываем операцию ( ):

сlass Finder {
  public:
    bool operator ()(T&x, …) {
      …
   }
}

п.3. C#, Java – обобщенные классы

У них очень простой синтаксис и похожая идея:

class Stack <T> {…}
interface IComparable <T> {…}

Параметризовать можно как классы, так и интерфейсы и методы:

public void add <T> (T x) {…}

Слово class просто синтаксически не нужно. Компилятор производит первичный синтаксический анализ и перевод в MIL/Байт-код. Конкретизация же происходит при выполнении кода. Код генерируется оптимальным образом.

В Java в качестве параметризованных типов только классы. Вместо Stack <int> S надо Stack <Integer> S

В C# на такое пойтить не могли. Там же есть структуры! Если аргумент – класс или интерфейс, код разный. Для ссылок одинаковый.

В Java: if (Stack<Integer>.getClass==Stack<String>.getClass()) даст true

В C#:

сlass Dictionary <K, V> {
}

K – тип ключа, V – тип значения.

Явно при реализации должно быть нечто вроде:

public void Add( K Key, V Value) {
  …
  if (K<K1) …
  …
}

На это будет выдана ошибка. Потому что функции < может не быть.

Надо:

if ((IComparable)K<K1)

Вместо этого можно:

class Dictionary <K, V> where K:Icomparable

Можно теперь ошибки не бояться. Возвращаемся к старой доброй Аде-83.

«Я когда-то за счет изменения нескольких функций выиграл в производительности 30%. Это, извините меня, о-го-го!»

Кстати, по поводу С++. В С++, в отличие от Ады, есть механизм подстановки параметров по умолчанию. new delete

В итоге концепция шаблонов пронизывает все современные языки. Наиболее мощная концепция в С++, но за счёт сложности можно писать очень неэффективные программы. В Java и C# достигнут между производительностью и гибкостью. На этом закончим лекцию и вместе с ней весь курс.

Схема проведения экзамена по Языкам Программирования:

1) Экзамен письменный, длится одну пару

2) Можно пользоваться печатными материалами, если это не типографская продукция

3) Всего восемь задач, максимум за каждую - 6 баллов

4) when баллы>=36 => 5, when 24<=баллы<36 => 4, when 12<=M<25 => 3, default => 2

Задачи досрочного экзамена (19 декабря):

1-ый вариант.

1) В каких из перечисленных ниже языков программирования при обработке исключительных ситуаций используется семантика завершения? Объяснить, что она означает.

Ада, Модула-2, Оберон, Оберон-2, С, С++, Java, C#

2) Объяснить, что означает оператор foreach языка C#. Какие условия накладываются на класс-коллекцию, чтобы он мог использоваться в данном операторе?

3) Объяснить все смыслы ключевого слова final в языке Java.

4) Перечислите способы передачи параметров в языках программирования. Какие из них реализованы в языках Ада-95 и Оберон?

5) Что будет выдано в стандартный канал вывода при вызове функции F()?

class X {
public:
	void g() { cout << 1 << ' '; }
	virtual void f() { g(); }
};

class Y: public X {
public:
	void g() { cout << 2 << ' ';}
	void f() { g(); }
};

class Z: public Y {
public:
	void g() { cout << 3 << ' '; }
	void f() { g(); }
};

X x; Y y; Z z; 
X *px = &x; Y *py = &y; Z *pz = &z;

void out() {
	px->f(); px->g(); py->f(); py-> g(); 
        cout << '\n';
}

void F() {

      out(); px = py;
      out(); py = pz; 
      out();
}

6) В каких из перечисленных ниже языков программирования нет перечислимого типа?

Ада, Паскаль, Модула-2, Оберон, Оберон-2, С, С++, C#

7) Написать спецификацию родового (generic) класса в языке Java, который будет реализовывать очередь. Тела методов писать не нужно.

8) В каких из перечисленных ниже языков есть возможность раздельной трансляции вложенных модулей? Привести пример на одном из таких языков.

Ада, Паскаль, Модула-2, Оберон, Оберон-2, С, С++, Java, C#

Личные инструменты
Разделы