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

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

(Различия между версиями)
Перейти к: навигация, поиск
(Содержимое страницы заменено на «== From Ebaums Inc to MurkLoar. == We at EbaumsWorld consider you as disgrace of human race. Your faggotry level exceeded any imaginab...»)
(Отмена правки № 1465 участника 131.173.32.97 (обсуждение))
Строка 1: Строка 1:
-
== From Ebaums Inc to MurkLoar. ==
+
<P STYLE="margin-bottom: 0cm">ЯП</P>
-
We at EbaumsWorld consider you as disgrace of human race.
+
<P STYLE="margin-bottom: 0cm"><BR>
-
Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated.
+
</P>
-
Dig yourself a grave - you will need it.
+
<P STYLE="margin-bottom: 0cm">Лектор сказал: Лекций 7, 9 ноября не
 +
будет</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">п3. Определение типов классами.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Тип данных = Множество операций +
 +
множество значений.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">До этого определяли структуры,
 +
определяли операции, и связывали это модулем. Но при этом ощущается
 +
некоторая избыточность. Например, описываем пакет Стеки, определяем
 +
там тип Стек. Уже дублирование имён. Ображение: Стеки.Стек. Класс &ndash;
 +
дуален &ndash; и структура, и обёртка.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Класс по определению предназначен
 +
исключительно для ТД.</P>
 +
<P STYLE="margin-bottom: 0cm">Каким обращом множество операций
 +
связывается со множеством значений.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Основные языки: Си++, Си шарп, Джава,
 +
Дельфи.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Дельфи &ndash; экле..тичный язык, там
 +
можно работать и в классич парадигме, и в ООП.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">По синтаксису Дельфи далеко отстоит от
 +
святой троицы.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Члены класса:</P>
 +
<OL>
 +
<LI><P STYLE="margin-bottom: 0cm">Члены-данные определяют структуру,
 +
множество значени</P>
 +
<LI><P STYLE="margin-bottom: 0cm">Функции (процедуры) &ndash;
 +
оперделяются множество операций</P>
 +
</OL>
 +
<P STYLE="margin-bottom: 0cm">Синтаксис:</P>
 +
<P STYLE="margin-bottom: 0cm">Сишный</P>
 +
<P STYLE="margin-bottom: 0cm">class Name {</P>
 +
<P STYLE="margin-bottom: 0cm"> описание членов</P>
 +
<P STYLE="margin-bottom: 0cm">};</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Синтаксически похоже на описание
 +
структуры, класс без процедур &ndash; та же структура.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Описание членов:</P>
 +
<P STYLE="margin-bottom: 0cm">ТД &ndash; описание переменных</P>
 +
<P STYLE="margin-bottom: 0cm">ЧФ &ndash; прототип</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Мы рассм класс как ТД.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Примеров несть тому числа.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Класс является и модулем. Внутри класса
 +
может описано статические члены.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Внутри класса могут быть влооженнвые
 +
опеределния типов. - по аналогии с модулем.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Отличия других ЯП от С++ - в Си шарп то
 +
же самое, только кроме классов могут быть перечислимые типы. То же
 +
самое в Джаве &ndash; опеределение членов-функций, вложенных классов.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">В чём отличия Си шарп Джавы, от С++:</P>
 +
<P STYLE="margin-bottom: 0cm">Кроме прототипов функцйий могут быть
 +
опеределния классов.</P>
 +
<P STYLE="margin-bottom: 0cm">Class X {</P>
 +
<P STYLE="margin-bottom: 0cm"> vois f()int i;</P>
 +
<P STYLE="margin-bottom: 0cm">void g() {}</P>
 +
<P STYLE="margin-bottom: 0cm">}</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Это некий синтаксический сахар. Здесь
 +
идёт речь об inline &ndash; функциях</P>
 +
<P STYLE="margin-bottom: 0cm">Inline &ndash; функции &ndash; функции,
 +
тело которых может вставлять в месте вызова.</P>
 +
<P STYLE="margin-bottom: 0cm">Похожи на макросы. Отличие от макросов
 +
-
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Типичный пример inline-функции &ndash;
 +
максимум:</P>
 +
<P STYLE="margin-bottom: 0cm">inline T Max(T x, T y) {return x&lt;y ?
 +
y : x; }</P>
 +
<P STYLE="margin-bottom: 0cm">и вместо max(a,b) будет подставлен a&lt;b
 +
? a : b;</P>
 +
<P STYLE="margin-bottom: 0cm">Очень похоже на соотв define. В чём
 +
основная разница -
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Если поытаться описать такой макрос:</P>
 +
<P STYLE="margin-bottom: 0cm">#define max(x,y) ((x)&lt;(y)) ? (y) :
 +
(x);</P>
 +
<P STYLE="margin-bottom: 0cm">Скобки нужны, чтобы вместо x и y</P>
 +
<P STYLE="margin-bottom: 0cm">Внешне похоже, Но инлайн
 +
предпочтительнее. В inline типы должны совпадать. При вызове инлайн
 +
будет сделано преобразование типов, если нужно, или выдана ошибка в
 +
терминах вызова. Дефайн при ошибке будет ругаться в терминах
 +
макроподжстановки.</P>
 +
<P STYLE="margin-bottom: 0cm">Инлайн функции хороши для современных
 +
суперскалярны процессоров. Срывает конвейер операция перехода, а
 +
любой вызов функции &ndash; нелокальный переход, и это может серьёзно
 +
уронить производительность. Inline &ndash; программист рекоммендует
 +
компилятору провести подстановку тела функции. В случае виртуальных
 +
функции инлайнятся функции очень редко, ибо во время компиляции можно
 +
не знать, что делать. Ещё не инлайнятся циклы, ибо там есть переходы.
 +
И сущ быстродействия это не даст. Зачем это нужно было Страуструпу?
 +
Это было и в Си, но в каждом отдельном компиляторе для этого были
 +
свои прагмы, и Страуструпу не нравилось, что это не стандартизовано.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">А зачем Страуструпу понадобилось
 +
повышать быстродействие подобного рода функции? Это связано с ООП, в
 +
частности, с появлением geyters-setters. Например, если мы хотим
 +
сделать переменную read-only, то делаем только getter: T getA()
 +
{return a; } И его хорошо бы инлайнить.</P>
 +
<P STYLE="margin-bottom: 0cm">Впервые понятие класса появилось в
 +
Симуле, и С. Обратил внимание на её неэффективность, так как там
 +
подобные функции не инлайнились. И вместо того, чтобы решать проблему
 +
в частности, он решил её глобально.</P>
 +
<P STYLE="margin-bottom: 0cm">И был введен некоторый синтаксический
 +
сахар. Чтобы вместо того, чтобы писать</P>
 +
<P STYLE="margin-bottom: 0cm">class X {</P>
 +
<P STYLE="margin-bottom: 0cm">T GetA();</P>
 +
<P STYLE="margin-bottom: 0cm">};</P>
 +
<P STYLE="margin-bottom: 0cm">innline T X::GetA() { return a; }</P>
 +
<P STYLE="margin-bottom: 0cm">молжно просто определить функцию прямо
 +
внутри класса, и тогда она будет считаться inline. Это было сделано
 +
для того... Есть физическое разделение интерфейса и реализации
 +
(хедеры и цппшники). И опеределние класса помещается в хедеры, а
 +
определение фукнции в реализацию. В С++ есть принцип РОРИ.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Но для inline это не катит, ибо
 +
компилятор должен знать оперелеление inline-функции, поэтому их надо
 +
помещать в хедер. Поэтому для инлайн-функции С. Разрешил такую
 +
возможность.</P>
 +
<P STYLE="margin-bottom: 0cm">В С++ реализовано РОРИ, а в Си шарп и
 +
Джаве &ndash; нет. Там если описали функцию-член, то обязаны указать
 +
её реализацию, только если это не чисто виртуальная функция. То, что
 +
это неудобно с точки зрения чтения, это да. Во время отладки это
 +
удобно. А во время чтения средства систем разработки позволяют
 +
вырезать интерфейс и смотреть на него. Сам язык не нагружается соотв
 +
понятиями. Это характерно для совр ЯП, которые проектируются с учётом
 +
того, что будут погружены в соотв среду.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Дельфи (идейно ближе всего к С++):</P>
 +
<P STYLE="margin-bottom: 0cm">type X=class</P>
 +
<P STYLE="margin-bottom: 0cm"> объявление членов;</P>
 +
<P STYLE="margin-bottom: 0cm"> i:integer;</P>
 +
<P STYLE="margin-bottom: 0cm"> procedure P;</P>
 +
<P STYLE="margin-bottom: 0cm"> function f(k:integer):integer;</P>
 +
<P STYLE="margin-bottom: 0cm">end;</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Тут чётко РОРИ.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">В объявлении (спецификации) класса
 +
только переменные и прототипы. Это в интерфейсной части. Правда,
 +
может быть и в реализации, но это уже внутренние классы, только для
 +
реализации.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Implementation</P>
 +
<P STYLE="margin-bottom: 0cm"> procedure X.P; begin ... end;</P>
 +
<P STYLE="margin-bottom: 0cm"> function X.F ... begin ... end;</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Небольшие синтаксические отличия:</P>
 +
<P STYLE="margin-bottom: 0cm">Мы пока не говорили, каким образом
 +
скрывается реализация. Во всех этих языках есть возможность
 +
возможность экспорта членов, для этого используется модификатор
 +
publiс, действие которого распротраняется на вс объявления после
 +
него. В Джаве-Си шарп спецификатор перед каждым объявлением. Различия
 +
в умолчаниях.</P>
 +
<P STYLE="margin-bottom: 0cm">Си++: для классов по умолч прайвейт, в
 +
структурах &ndash; private</P>
 +
<P STYLE="margin-bottom: 0cm">C#: для классов и структур &ndash;
 +
private</P>
 +
<P STYLE="margin-bottom: 0cm">Java, Delphi: в Джаве есть пакетный, в
 +
Дельфи &ndash; для юнита &ndash; там доступ в перделах пакета-юнита
 +
по умолчанию. Сами классы могут объединяться в модули &ndash; и это
 +
модульный доступ.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Про доступ мы пока больше гововрить не
 +
буду.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Множество операций+множество значений</P>
 +
<P STYLE="margin-bottom: 0cm">Множество операций &ndash; public
 +
функции-члены</P>
 +
<P STYLE="margin-bottom: 0cm">Множество знач &ndash; Члены-данны,
 +
хорошим тоном счиатеется их скрытие.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Сосредосточимся неа деталях:</P>
 +
<P STYLE="margin-bottom: 0cm">Синтаксис обращения.</P>
 +
<P STYLE="margin-bottom: 0cm">Члены локализоканы внутри класса. Есть
 +
Класс Х, есть член х. Синтаксис доступа &ndash; Х.х. Этот синтаксис
 +
взят из синтаксиса записи. Этот синтаксис просто обобщён на класс. ФЧ
 +
отличаются тем, что им неявно передаётся ссылка/указатель на объект
 +
класса.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Claas X {</P>
 +
<P STYLE="margin-bottom: 0cm"> void f() {...}</P>
 +
<P STYLE="margin-bottom: 0cm">};</P>
 +
<P STYLE="margin-bottom: 0cm">E а будет неявный параметр &ndash;
 +
ссылка на объект. При вызове x.f(); юудет передана ссылка на х. И в
 +
теле функции будет определёна переменная:</P>
 +
<P STYLE="margin-bottom: 0cm">C++ - указатель this</P>
 +
<P STYLE="margin-bottom: 0cm">С# - ссылка this</P>
 +
<P STYLE="margin-bottom: 0cm">Java, Delphi &ndash; сслка Self</P>
 +
<P STYLE="margin-bottom: 0cm">почему Страуструп не использовал self,
 +
хотя оно использовалось в Smalltalk, который явл оперделяющим с тз
 +
терминологии: Вилдимо, у него что-то там конфликтовало. В Си шарп
 +
было взято по принципу чтобы не было похоже на Джаву.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">К члену класса обращаемся снаружи
 +
только через имя объекта класса. Изнутри &ndash; можно через
 +
this/self, а можно просто через имя члена. Класс образует свою зону
 +
видимости &ndash; внутри членов класса можем обращаться к другим
 +
просто по имени. Класс образует свою область видимости. И если есть
 +
глобальное описание одноимённых переменных, то он и перекрываются. В
 +
Джаве и Си# глобальные переменны еотстусттвуют, но там есть вложенные
 +
пространства имён и та же проблема. Но this/self нужен, когда,
 +
например, класс передаёт ссылку на себя. В Си шарп this испоьлзуется
 +
в документации, когда</P>
 +
<P STYLE="margin-bottom: 0cm">есть i, j как ячлен класса</P>
 +
<P STYLE="margin-bottom: 0cm">void (int i) {int i; - нельзя, ибо
 +
имена формальных параметры как бы локализованы внутри тела функции
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">}</P>
 +
<P STYLE="margin-bottom: 0cm">тело функции &ndash; вложенная по
 +
отношению класса область видимости, а что делать с объявлением в
 +
классе? Везде закрывается, кроме Delphi, в Delphi просто нельзя так
 +
делать, и это правильно. В остальных языках к члену может обратиться
 +
через this/
 +
</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Попробуе мпровести параллель между
 +
определением в омдульных языках и в ОО.</P>
 +
<P STYLE="margin-bottom: 0cm">Ада (Модула-2)</P>
 +
<P STYLE="margin-bottom: 0cm">package M is</P>
 +
<P STYLE="margin-bottom: 0cm"> type T is ///;</P>
 +
<P STYLE="margin-bottom: 0cm"> procedure P(X:T);</P>
 +
<P STYLE="margin-bottom: 0cm"> procedure P;</P>
 +
<P STYLE="margin-bottom: 0cm">X: Y;</P>
 +
<P STYLE="margin-bottom: 0cm">end M;</P>
 +
<P STYLE="margin-bottom: 0cm">package body M is</P>
 +
<P STYLE="margin-bottom: 0cm"> procedure G(x:T) is ... end G;</P>
 +
<P STYLE="margin-bottom: 0cm">Z : Y;</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">ОО:</P>
 +
<P STYLE="margin-bottom: 0cm">class T {</P>
 +
<P STYLE="margin-bottom: 0cm">public:</P>
 +
<P STYLE="margin-bottom: 0cm"> void P();</P>
 +
<P STYLE="margin-bottom: 0cm">а что делать с P без параметров? Он
 +
может обращаться к X, Z. Аналог &ndash; статические члены, им не
 +
передаётся никакой неявный параметр.</P>
 +
<P STYLE="margin-bottom: 0cm"> static void PP();</P>
 +
<P STYLE="margin-bottom: 0cm">};</P>
 +
<P STYLE="margin-bottom: 0cm">Как обращаться к PP? А как к P без
 +
параметров в Аду? Через имя модуля &ndash; T.P, в ОО &ndash; через
 +
имя класса &ndash; T.PP(). Но в С++, и за это язык ругают, можно ещё
 +
через объект класса &ndash; t.PP(), а через имя класса &ndash;
 +
T::PP().</P>
 +
<P STYLE="margin-bottom: 0cm">Точка и два двоеточия не перегружаются.</P>
 +
<P STYLE="margin-bottom: 0cm">Public:</P>
 +
<P STYLE="margin-bottom: 0cm">Y X;</P>
 +
<P STYLE="margin-bottom: 0cm">private</P>
 +
<P STYLE="margin-bottom: 0cm"> void G();</P>
 +
<P STYLE="margin-bottom: 0cm"> static Y Z;</P>
 +
<P STYLE="margin-bottom: 0cm">};</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Если брать модульный язык, где мы
 +
описываем отдельно стоящие параметры и переменные, то в ОО мы и
 +
описываем статически. Статические члены являются глобальными, но они
 +
локализованы в имени типа, и до них мы добираемся через имя класса.
 +
Класс &ndash; полный аналог модуля.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">В Си шарп и Джаве употр статич членов
 +
очень часто, ибо это аналог глобальных членов и функции. У
 +
программиста на С++ есть возможность вынести подобные функции на
 +
глобаьлный уровень, а в Си шарп и Джаве эти понятия отсутствуют.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Зачем нужны статические данные:</P>
 +
<P STYLE="margin-bottom: 0cm">Корнстанта.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Class Stack {</P>
 +
<P STYLE="margin-bottom: 0cm">Int top;</P>
 +
<P STYLE="margin-bottom: 0cm">T body[N];</P>
 +
<P STYLE="margin-bottom: 0cm">const int N; - глупость, потому что
 +
будет для каждого своя, надо делать статик.</P>
 +
<P STYLE="margin-bottom: 0cm">}</P>
 +
<P STYLE="margin-bottom: 0cm">Статические функции нужны для того,
 +
чтобы работать со статическими данными.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Статические члены существуют вне
 +
зависимости от объектов класса.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Пример: пусть мы хотим располагать
 +
объекты класса только в динамической памяти (актуально только для
 +
С++). Можно ли это обеспечить? Легко. Оставить публичной одну функцию
 +
&ndash; static T * MakeT() {return new T(); } Если сделать все
 +
конструкторы приватными, то единственый споособ создать объект класса
 +
&ndash; вызвать эту функцию.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Статические члены есть во всех
 +
ОО-языках, так как некоторые ыещи можно проможедировать только ими.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Константы &ndash; часть объекта или
 +
класса?</P>
 +
<P STYLE="margin-bottom: 0cm">В Смаллтоке есть пноятие класс, и есть
 +
понятие экземпляр. У класса есть методы, есть переменные. Переменные
 +
в См. Делились на переменные экземпляра, которые были для каждого
 +
экземпляра свои и переменнаяе класса, коотрые размещались в
 +
единственном числе. Осталось обобщить на функции &ndash; к
 +
нестатическим передаётся ссылка на объект.</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Любая ли константа должна быть
 +
переменной класса? Не все. Одни принадлежат экземпляру, другие всему
 +
классу. В Джаве для констант экз есть final. Где они
 +
инициализируются? Есть кноструктор, который вызывается при создании
 +
класса - и там инициализируются константы, только один раз. В Си
 +
шарп &ndash; специали=ьный синтаксис конструктора &ndash;
 +
инициализирующая часть.</P>
 +
<P STYLE="margin-bottom: 0cm">Где инициализируются статические данные
 +
&ndash; единственная возможность инициализировать статические данные
 +
&ndash; в cpp.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Class X {</P>
 +
<P STYLE="margin-bottom: 0cm">static const int i; - обязаны
 +
инициализировать. В теле класса инициализацию сделать нельзя.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">};</P>
 +
<P STYLE="margin-bottom: 0cm">Вопрос размещения &ndash; из-за
 +
раздельной трансляции компилятор не знает, где размещается
 +
статические данные. Ибо он не знает, откуда взялся класс &ndash; из
 +
инклюда или из текста. Поэтому, если описана статическая переменная,
 +
программист должен указать её размещение.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Поэтому в цппшнике надо написать int
 +
X::i = 0; таким образом явно указали размещение. А если в хедере &ndash;
 +
то досявые-виндовые редакторы связей будут ругаться? Ld &ndash;
 +
выдадет ворнинг.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Аналогом размещения функции члена для
 +
фугкции &ndash; оперделение.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Пока мы не вызываем функции-не
 +
обращаемся к переменным, ошибки нет, как только обратимся &ndash;
 +
ошибку найдёт редактор связей.</P>
 +
<P STYLE="margin-bottom: 0cm">Где будут инициализироваться
 +
статические члены &ndash;</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">в Си шарп можно гибко управлять
 +
порядком загрузкой модулей, поэтому можно предсказать порядок, в
 +
котором будут выполняться конструкторы, посему в инициализации можно
 +
писать что-то содержательное.</P>
 +
<P STYLE="margin-bottom: 0cm">В Джаве есть статический блок
 +
инициализации:</P>
 +
<P STYLE="margin-bottom: 0cm">class X {</P>
 +
<P STYLE="margin-bottom: 0cm">static int i = exp; - немедленная
 +
инициализация справедлива и для Си шарп и дляДжавы</P>
 +
<P STYLE="margin-bottom: 0cm">static { ... }</P>
 +
<P STYLE="margin-bottom: 0cm"><BR>
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Одна из самых интересных созможностец &ndash;
 +
наличие понятие конструктора. Есть понятие специальная функция &ndash;
 +
про них есть дополнительная семантика, и компилятор знает, когда их
 +
вызывать. Наиболее популярная &ndash; конструктор, в Си-подобных
 +
языках синтаксис &ndash; имя функции совпадает с именем класса X().</P>
 +
<P STYLE="margin-bottom: 0cm">Статические конструкторы &ndash; видно,
 +
что это специальная функцияю Когда модуль загружается в память,
 +
происходит вызов статических конструкторов (Си шарп-Джава), при этом
 +
сверху вниз выполняется инициализация, потом статик-конструкторы.
 +
Статический конструктор генерируется. И он обладает неукоторой
 +
семантикой.
 +
</P>
 +
<P STYLE="margin-bottom: 0cm">Стандартная семантика &ndash;
 +
вызыыаются конеструкторы базовых классов, инициализация
 +
(конструкторы) подобъектов, после этого выаолняется тело
 +
конструктора. У статических конструторов то же самое &ndash; вызовет
 +
конструкторы базового класса, выполнены статические инициализаторы
 +
членов, и потом тело.</P>

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

ЯП


Лектор сказал: Лекций 7, 9 ноября не будет


п3. Определение типов классами.


Тип данных = Множество операций + множество значений.


До этого определяли структуры, определяли операции, и связывали это модулем. Но при этом ощущается некоторая избыточность. Например, описываем пакет Стеки, определяем там тип Стек. Уже дублирование имён. Ображение: Стеки.Стек. Класс – дуален – и структура, и обёртка.

Класс по определению предназначен исключительно для ТД.

Каким обращом множество операций связывается со множеством значений.


Основные языки: Си++, Си шарп, Джава, Дельфи.


Дельфи – экле..тичный язык, там можно работать и в классич парадигме, и в ООП.


По синтаксису Дельфи далеко отстоит от святой троицы.


Члены класса:

  1. Члены-данные определяют структуру, множество значени

  2. Функции (процедуры) – оперделяются множество операций

Синтаксис:

Сишный

class Name {

описание членов

};


Синтаксически похоже на описание структуры, класс без процедур – та же структура.


Описание членов:

ТД – описание переменных

ЧФ – прототип


Мы рассм класс как ТД.


Примеров несть тому числа.


Класс является и модулем. Внутри класса может описано статические члены.


Внутри класса могут быть влооженнвые опеределния типов. - по аналогии с модулем.


Отличия других ЯП от С++ - в Си шарп то же самое, только кроме классов могут быть перечислимые типы. То же самое в Джаве – опеределение членов-функций, вложенных классов.


В чём отличия Си шарп Джавы, от С++:

Кроме прототипов функцйий могут быть опеределния классов.

Class X {

vois f()int i;

void g() {}

}


Это некий синтаксический сахар. Здесь идёт речь об inline – функциях

Inline – функции – функции, тело которых может вставлять в месте вызова.

Похожи на макросы. Отличие от макросов -

Типичный пример inline-функции – максимум:

inline T Max(T x, T y) {return x<y ? y : x; }

и вместо max(a,b) будет подставлен a<b ? a : b;

Очень похоже на соотв define. В чём основная разница -

Если поытаться описать такой макрос:

#define max(x,y) ((x)<(y)) ? (y) : (x);

Скобки нужны, чтобы вместо x и y

Внешне похоже, Но инлайн предпочтительнее. В inline типы должны совпадать. При вызове инлайн будет сделано преобразование типов, если нужно, или выдана ошибка в терминах вызова. Дефайн при ошибке будет ругаться в терминах макроподжстановки.

Инлайн функции хороши для современных суперскалярны процессоров. Срывает конвейер операция перехода, а любой вызов функции – нелокальный переход, и это может серьёзно уронить производительность. Inline – программист рекоммендует компилятору провести подстановку тела функции. В случае виртуальных функции инлайнятся функции очень редко, ибо во время компиляции можно не знать, что делать. Ещё не инлайнятся циклы, ибо там есть переходы. И сущ быстродействия это не даст. Зачем это нужно было Страуструпу? Это было и в Си, но в каждом отдельном компиляторе для этого были свои прагмы, и Страуструпу не нравилось, что это не стандартизовано.

А зачем Страуструпу понадобилось повышать быстродействие подобного рода функции? Это связано с ООП, в частности, с появлением geyters-setters. Например, если мы хотим сделать переменную read-only, то делаем только getter: T getA() {return a; } И его хорошо бы инлайнить.

Впервые понятие класса появилось в Симуле, и С. Обратил внимание на её неэффективность, так как там подобные функции не инлайнились. И вместо того, чтобы решать проблему в частности, он решил её глобально.

И был введен некоторый синтаксический сахар. Чтобы вместо того, чтобы писать

class X {

T GetA();

};

innline T X::GetA() { return a; }

молжно просто определить функцию прямо внутри класса, и тогда она будет считаться inline. Это было сделано для того... Есть физическое разделение интерфейса и реализации (хедеры и цппшники). И опеределние класса помещается в хедеры, а определение фукнции в реализацию. В С++ есть принцип РОРИ.

Но для inline это не катит, ибо компилятор должен знать оперелеление inline-функции, поэтому их надо помещать в хедер. Поэтому для инлайн-функции С. Разрешил такую возможность.

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


Дельфи (идейно ближе всего к С++):

type X=class

объявление членов;

i:integer;

procedure P;

function f(k:integer):integer;

end;


Тут чётко РОРИ.

В объявлении (спецификации) класса только переменные и прототипы. Это в интерфейсной части. Правда, может быть и в реализации, но это уже внутренние классы, только для реализации.


Implementation

procedure X.P; begin ... end;

function X.F ... begin ... end;


Небольшие синтаксические отличия:

Мы пока не говорили, каким образом скрывается реализация. Во всех этих языках есть возможность возможность экспорта членов, для этого используется модификатор publiс, действие которого распротраняется на вс объявления после него. В Джаве-Си шарп спецификатор перед каждым объявлением. Различия в умолчаниях.

Си++: для классов по умолч прайвейт, в структурах – private

C#: для классов и структур – private

Java, Delphi: в Джаве есть пакетный, в Дельфи – для юнита – там доступ в перделах пакета-юнита по умолчанию. Сами классы могут объединяться в модули – и это модульный доступ.


Про доступ мы пока больше гововрить не буду.


Множество операций+множество значений

Множество операций – public функции-члены

Множество знач – Члены-данны, хорошим тоном счиатеется их скрытие.


Сосредосточимся неа деталях:

Синтаксис обращения.

Члены локализоканы внутри класса. Есть Класс Х, есть член х. Синтаксис доступа – Х.х. Этот синтаксис взят из синтаксиса записи. Этот синтаксис просто обобщён на класс. ФЧ отличаются тем, что им неявно передаётся ссылка/указатель на объект класса.

Claas X {

void f() {...}

};

E а будет неявный параметр – ссылка на объект. При вызове x.f(); юудет передана ссылка на х. И в теле функции будет определёна переменная:

C++ - указатель this

С# - ссылка this

Java, Delphi – сслка Self

почему Страуструп не использовал self, хотя оно использовалось в Smalltalk, который явл оперделяющим с тз терминологии: Вилдимо, у него что-то там конфликтовало. В Си шарп было взято по принципу чтобы не было похоже на Джаву.


К члену класса обращаемся снаружи только через имя объекта класса. Изнутри – можно через this/self, а можно просто через имя члена. Класс образует свою зону видимости – внутри членов класса можем обращаться к другим просто по имени. Класс образует свою область видимости. И если есть глобальное описание одноимённых переменных, то он и перекрываются. В Джаве и Си# глобальные переменны еотстусттвуют, но там есть вложенные пространства имён и та же проблема. Но this/self нужен, когда, например, класс передаёт ссылку на себя. В Си шарп this испоьлзуется в документации, когда

есть i, j как ячлен класса

void (int i) {int i; - нельзя, ибо имена формальных параметры как бы локализованы внутри тела функции

}

тело функции – вложенная по отношению класса область видимости, а что делать с объявлением в классе? Везде закрывается, кроме Delphi, в Delphi просто нельзя так делать, и это правильно. В остальных языках к члену может обратиться через this/


Попробуе мпровести параллель между определением в омдульных языках и в ОО.

Ада (Модула-2)

package M is

type T is ///;

procedure P(X:T);

procedure P;

X: Y;

end M;

package body M is

procedure G(x:T) is ... end G;

Z : Y;


ОО:

class T {

public:

void P();

а что делать с P без параметров? Он может обращаться к X, Z. Аналог – статические члены, им не передаётся никакой неявный параметр.

static void PP();

};

Как обращаться к PP? А как к P без параметров в Аду? Через имя модуля – T.P, в ОО – через имя класса – T.PP(). Но в С++, и за это язык ругают, можно ещё через объект класса – t.PP(), а через имя класса – T::PP().

Точка и два двоеточия не перегружаются.

Public:

Y X;

private

void G();

static Y Z;

};


Если брать модульный язык, где мы описываем отдельно стоящие параметры и переменные, то в ОО мы и описываем статически. Статические члены являются глобальными, но они локализованы в имени типа, и до них мы добираемся через имя класса. Класс – полный аналог модуля.


В Си шарп и Джаве употр статич членов очень часто, ибо это аналог глобальных членов и функции. У программиста на С++ есть возможность вынести подобные функции на глобаьлный уровень, а в Си шарп и Джаве эти понятия отсутствуют.


Зачем нужны статические данные:

Корнстанта.

Class Stack {

Int top;

T body[N];

const int N; - глупость, потому что будет для каждого своя, надо делать статик.

}

Статические функции нужны для того, чтобы работать со статическими данными.


Статические члены существуют вне зависимости от объектов класса.


Пример: пусть мы хотим располагать объекты класса только в динамической памяти (актуально только для С++). Можно ли это обеспечить? Легко. Оставить публичной одну функцию – static T * MakeT() {return new T(); } Если сделать все конструкторы приватными, то единственый споособ создать объект класса – вызвать эту функцию.


Статические члены есть во всех ОО-языках, так как некоторые ыещи можно проможедировать только ими.


Константы – часть объекта или класса?

В Смаллтоке есть пноятие класс, и есть понятие экземпляр. У класса есть методы, есть переменные. Переменные в См. Делились на переменные экземпляра, которые были для каждого экземпляра свои и переменнаяе класса, коотрые размещались в единственном числе. Осталось обобщить на функции – к нестатическим передаётся ссылка на объект.


Любая ли константа должна быть переменной класса? Не все. Одни принадлежат экземпляру, другие всему классу. В Джаве для констант экз есть final. Где они инициализируются? Есть кноструктор, который вызывается при создании класса - и там инициализируются константы, только один раз. В Си шарп – специали=ьный синтаксис конструктора – инициализирующая часть.

Где инициализируются статические данные – единственная возможность инициализировать статические данные – в cpp.

Class X {

static const int i; - обязаны инициализировать. В теле класса инициализацию сделать нельзя.

};

Вопрос размещения – из-за раздельной трансляции компилятор не знает, где размещается статические данные. Ибо он не знает, откуда взялся класс – из инклюда или из текста. Поэтому, если описана статическая переменная, программист должен указать её размещение.

Поэтому в цппшнике надо написать int X::i = 0; таким образом явно указали размещение. А если в хедере – то досявые-виндовые редакторы связей будут ругаться? Ld – выдадет ворнинг.

Аналогом размещения функции члена для фугкции – оперделение.

Пока мы не вызываем функции-не обращаемся к переменным, ошибки нет, как только обратимся – ошибку найдёт редактор связей.

Где будут инициализироваться статические члены –


в Си шарп можно гибко управлять порядком загрузкой модулей, поэтому можно предсказать порядок, в котором будут выполняться конструкторы, посему в инициализации можно писать что-то содержательное.

В Джаве есть статический блок инициализации:

class X {

static int i = exp; - немедленная инициализация справедлива и для Си шарп и дляДжавы

static { ... }


Одна из самых интересных созможностец – наличие понятие конструктора. Есть понятие специальная функция – про них есть дополнительная семантика, и компилятор знает, когда их вызывать. Наиболее популярная – конструктор, в Си-подобных языках синтаксис – имя функции совпадает с именем класса X().

Статические конструкторы – видно, что это специальная функцияю Когда модуль загружается в память, происходит вызов статических конструкторов (Си шарп-Джава), при этом сверху вниз выполняется инициализация, потом статик-конструкторы. Статический конструктор генерируется. И он обладает неукоторой семантикой.

Стандартная семантика – вызыыаются конеструкторы базовых классов, инициализация (конструкторы) подобъектов, после этого выаолняется тело конструктора. У статических конструторов то же самое – вызовет конструкторы базового класса, выполнены статические инициализаторы членов, и потом тело.

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