лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел), страница 9
Описание файла
PDF-файл из архива "лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 9 страницы из PDF
им нужно хранить дополнительную информацию(является ли функция виртуальной, …).int x?* p;p=&X?i;//можноp=&X?j;//можноvoid (X?* pfX)();pfX=&X?f; //можноpfX=&X?g; //можноX anX, *pX;anX.*p;//обращениеanX.*pfX(); //обращениеpX>*p;.*, >* - новые операции.Замечание о константности.class X {const int ii; //нельзя инициализировать в определенииstatic const int i;};ii сохраняет одно и то же значение на протяжении всей жизни объекта.В С#:const int i = expr;//это говорит о том, что expr должно быть вычислимо на этапетрансляции.Так определенные константы всегда статические.readonly a = expr;// может быть инициализирован в любое время, но после этого неможет быть измененВ java такого отличия от С++ нет, но есть модификатор final, означающий неизменяемость.Вложенные типы (члены-типы).С++:class X {public:class Y {};};Y – вложенный класс.
Он – то же самое, что глобальный класс, но его имя локализовано в классе X и онимеет полный доступ к членам класса X.Пример: в STL любой контейнер имеет вложенный тип iterator (напр.).В языках Java и C# есть понятие статического вложенного класса.Вложенные классы в Java.Статический вложенный класс – то же самое, что вложенный класс в С++ (аналогичен статическойфункции). Нестатический вложенный класс – класс, который очень глубоко связан с объемлющим классом.Любой вложенный класс имеет ссылку на объект объемлющего класса.
Обратное, в общем случае, неверно.class BankAccount {int money;class Action {int k;void f () { ... money=k; }// можем обращаться к членам объемлющего классаvoid deposit(sum){this.new Action//вместо этого можно просто new Action()}};Создание объекта вложенного класса возможно только в контексте указателя на объемлющий класс.BankAccount x;BankAccount.Action a;a = x.new Action();Т.о. объект a имеет как бы 2 this.С использованием такого механизма и сборки мусора можно программировать сложные структуры. Естьанонимные внутренние классы – внутренние классы блока, могут ссылаться на локальные объекты.
В C#тоже есть понятие нестатического вложенного класса. Нестатический вложенный класс C# аналогиченстатическому вложенному классу Java (и вложенный класс С++).static class X { .. }; - может содержать только статические члены-данные истатические члены-функции.Зачем нужно такое понятие? Для классов, которым не нужны нестатические члены.class Math {...};Math m = new Math(); // бессмысленно, следовательно нужно использовать staticstatic class Math { ..
}; // ведет себя как модуль – содержит набор глобальныхфункций и констант, локализованных внутри класса.Нельзя порождать объекты такого класса, нельзя его наследовать.Замечание о Delphi. В нем есть понятие класса, членов-данных и членов-функций. Вложенных типов истатических членов нет. Они не нужны, т.к. Delphi имеет одновременно и модульную, и классовуюструктуру.unit M;interfacetype X=class;x:integer;procedure count;end;Здесь глобальные функции, описанные в unit M с точки зрения доступа - аналог статический членов класса,таким образом, нужды в статических членов нет.Инкапсуляция.Для классовых ЯП она заключается в ограничении доступа (в модульных языках (Ада, Оберон, Модула2) –ограничение видимости, а не доступа).
Самая простая модель – в С++. Есть три уровня доступа – public,private, protected. Рассматриваются три категории функции: функции-члены класса, функции-членыпроизводного класса, остальные функции.•••public – любая функция имеет доступprotected – только функции-члены класса и производных классовprivate – только функции-члены классаПроблема – как переопределить оператор +? Как функцию-член или как глобальную функцию?T T?operator +(const T& t);T operator +(const T& t1, const T& t2);C точки зрения семантики вторая форма более естественна, с точки зрения доступа – первая.
Естьметодики, позволяющие реализовывать операцию + через операцию +=, без доступа к членам класса.Однако, иногда нужно реализовывать глобальные функции, тесно связанные с реализацией класса. Поэтомув С++ введен механизм друзей. Функция-друг обладает такими же правами доступа, как функция-член.Отношение дружбы не наследуется, нельзя набиться в друзья. Это отношение не транзитивно, несимметрично.В других языках отношения защиты более сложные.Откуда берутся друзья? Обычно, они находятся в рамках одного проекта.В С# есть понятие Assembly – сборка (надязыковое понятие).
В Java – Package. Т.о. дополнительновводится еще одна категория функций – функции-члены из того же пакета (сборки). Таким образом, есть 4категории : функции-члены класса(1), функции-члены производного класса(2), функции-члены из того жепакета (сборки)(3), остальные функции(4).[lect24]II) Инкапсуляция в классахТри типа: public, protected, private. Они задаются жестко,поэтому понадобились friend. По умолчанию в структуре private –для совместимости со старыми структурами в стиле Си, а в классе –public.В Java используется пакетный доступ (package, контекст), в C# internal (namespace, assembly).C++свойнаследникмирpublic+++protected++-private---В таблице * означает, что имеются различия между C# и Java,зависимость в своей сборке мы или нет.В Delphi есть public, private, по умолчанию,protected.
Все в привычном понимании, аумолчание - это фактически совпадение с internal(пакетным типом), т.е. по отношению к своемумодулю они ведут себя как public, к другому – какprivate.C#/Javaсвойнаследниквзаимосвяз.мирpublic++++protected+++*-Абстрактный тип данных (АТД) – в первомприближении (с точки зрения класса) – это класс, укоторого публичными являются только процедуры,функции или, может быть, другие классы.internal++*+-private+---Рефакторинг – изменение кода без изменения функциональности, но с увеличением качества (например,введение getters/setters).Заметьте – абстрактный класс не является абстрактным типом данных, хотя и является типом данных иабстрактен как класс. Эти понятия ортогонально и не связаны. Наивный смысл protected – если член классапомечен как protected, то к нему есть доступ из любого наследника.
Такой смысл реализован в Delphi.Пример на C++:class X {private:int i;public:void f() { i = 0; }void g(X &x) { x.i = 0; }};class Y: public X {public:void f() { i = 0; }void g(X &x) { x.i = 0; }};//ясное дело работает//и это тоже работает!//не работает, если i – protected, можно если Y &xНи в одном языке (которые мы изучаем) нет других отношений между классами кроме наследования. Т.е.«братья» и «сестры» являются чужаками. Для соблюдения инкапсуляции в примере нет доступа в наивномсмысле, он есть только в Delphi (непонятно почему).III) Создание и уничтожение объектов (классов)Всегда у каждого класса есть хотя бы один конструктор, который вызывается при создании классов.
ВDelphi, C#, Java – референциальная модель (объекты только в динамической памяти).В С++•••же объекты бывают трех типов:статическиеквазистатическиединамическиеВ Delphi конструкторы выделяются именем constructor, они наследуются и называются обычно Create илиLoad (для persistent objects – загружаемых объектов). Тут нет таксономии конструкторов (т.к. в любомклассе есть конструктор – они наследуются), а во всех других языках – есть (в них нужен конструктор поумолчанию, он есть всегда).В С++ инициализация подобъектов происходит в конструкторах объектов (по-другому и быть не может).Если она не задана, то код будет сгенерирован автоматически. Сначала будет вызван конструктор базовогокласса, потом подобъекта, а лишь потом объекта. В С# для подобъектов этого не произойдет, т.к.подобъект – лишь ссылка, и она будет обнулена.
Это не страшно, т.к. пока нет подобъекта как такового, аесть лишь ссылка. Можно написать так:class X: Base {Y a = new X();X() {};}Список инициализации – есть в С++, в классах идет перед телом, необязателен для указания, ноприсутствует всегда (генерируется автоматически).
Конструктор по умолчанию так называется, потому чтовызывается для базового класса и подобъектов автоматически. Пример такого списка:X(0), Base(1), i(0) //последнее эквивалентно i = 0 с точностью до порядка вызововВ С# и Java конструкторы подобъектов автоматически не вызываются, их надо указывать явно. Синтаксисв этих языках отличается, но смысл тот же (для списков инициализации). В С++ сначала вызываетсяконструкторы подобъектов, а лишь затем базовых классов. Поэтому в конструкторе нельзя вызыватьвиртуальные методы – класса как такового еще не сконструировано и нет таблицы виртуальных методов.Т.е.