<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Программирование для начинающих на С++</title>
	<atom:link href="http://cppstudio.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://cppstudio.com</link>
	<description>Основы программирования на C/С++(Си++) для начинающих и новичков</description>
	<lastBuildDate>Sat, 26 May 2018 18:12:39 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>Особенности Qt: слоты и сигналы, описание QObject и QApplication, виды окон и т.д.</title>
		<link>http://cppstudio.com/post/11167/</link>
		<comments>http://cppstudio.com/post/11167/#comments</comments>
		<pubDate>Tue, 25 Aug 2015 15:28:14 +0000</pubDate>
		<dc:creator><![CDATA[tenebris]]></dc:creator>
				<category><![CDATA[Библиотека Qt]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=11167</guid>
		<description><![CDATA[Вводная часть: Qt – это не только элементы графического интерфейса. Этот фреймворк представляет собой взаимосвязанную систему. Родственность Qt-объектов осуществляется через наследование класса QObject. А связи между ними через сигнально-слотовую систему.В этой статье будут описаны основные классы и полезные особенности этой библиотеки. QObject Это базовый класс для всех объектов Qt. Его наследует любой класс использующий сигналы и слоты. Он обеспечивает возможность соединения объектов друг с другом. А также предоставляет к этому полезную функциональность. Во введение этого &#8230; <a href="http://cppstudio.com/post/11167/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<h3 style="text-align: justify;">Вводная часть:</h3>
<p>Qt – это не только элементы графического интерфейса. Этот фреймворк представляет собой взаимосвязанную систему. Родственность Qt-объектов осуществляется через наследование класса <code>QObject</code>. А связи между ними через сигнально-слотовую систему.В этой статье будут описаны основные классы и полезные особенности этой библиотеки.</p>
<hr />
<h4 style="text-align: justify;">QObject</h4>
<p style="text-align: justify;">Это базовый класс для всех объектов Qt. Его наследует любой класс использующий сигналы и слоты. Он обеспечивает возможность соединения объектов друг с другом. А также предоставляет к этому полезную функциональность. Во введение этого базового класса находиться:</p>
<ul>
<li style="text-align: justify;">Прослеживание за потомками и родителями и возвращение указателей на них (Наследственная информация).</li>
<li style="text-align: justify;">Программная реализация таймера</li>
<li style="text-align: justify;">Динамические свойства</li>
<li style="text-align: justify;">Интернационализация приложения</li>
</ul>
<h4 style="text-align: justify;">QApplication</h4>
<p style="text-align: justify;">Это сердце любого приложения использующего графические элементы.Объект этого класса должен быть создан в единственном экземпляре перед основным кодом программы. В его сферу ответственности входит:</p>
<ul>
<li>Инициализирует приложение в соответствии с пользовательскими настройками.</li>
<li>Выполняет обработку сообщений и передачу их соответствующим виджетам.</li>
<li>Анализирует аргументы командной строки и соответствующим образом устанавливает свой внутреннее состояние.</li>
<li>Определяет внешний вид приложения через установку стиля и изменение разрешенных цветов.</li>
<li>Предоставляет ссылки на глобальный буфер обмена(<code>clipboard()</code>) и другие полезные объекты.</li>
<li>Следит за открытыми окнами приложения и может выдать информацию о них.</li>
<li>Управляет видом иконки курсора.</li>
<li>И другие полезные функции.</li>
</ul>
<h4 style="text-align: justify;">Слоты и сигналы:</h4>
<p style="text-align: justify;">Для того чтобы объекты могли общаться, был введён <span style="text-decoration: underline;">механизм сигналов и слотов</span>. С помощью этого объекты сообщают друг другу о произошедших событиях и отсылают нужные данные. Слот, как и функция-член, может быть публичной, приватной, защищённой или виртуальной. Он вызывается, если приходит подсоединённый к нему сигнал. Он в свою очередь генерируется, если в коде обработки события имеется вызов(макрос) <code>emit signal().</code></p>
<p style="text-align: justify;"><em>Для себя можно представить определенную схему:</em></p>
<p style="text-align: justify;"><span class="label label-default">Событие </span><strong>➞</strong><span class="label label-default">Генерация сигнала</span><strong>➞</strong><span class="label label-default">Передача параметров в слот.</span></p>
<p style="text-align: justify;"><em>Как выглядит в программе:</em></p>
<p style="text-align: justify;"><span class="badge">&#171;Щелчок по кнопке&#187;</span> ➞ <span class="badge">программная обработка</span> ➞ <span class="badge">signal(clicked()) </span>➞ <span class="badge">slot(myslot()).</span></p>
<h4 style="text-align: justify;"></h4>
<h4 style="text-align: justify;">Основа для создания:</h4>
<p style="text-align: justify;">В классе, который должен будет иметь свои сигналы и слоты, нужно произвести наследование от <code>QObject</code> или другого класса библиотеки, наследующего его, и определить макрос <code>Q_Object</code>, с помощью этого объявления компилятор понимает, что необходимо сгенерировать из написанного qt-кода, который использует свои нововведения, в равнозначный шаблонный код стандартного C++. Начиная с Qt 5.0 появился новый способ соединения:</p>
<p style="text-align: justify;"><strong>1)Ранняя версия: </strong></p>
<pre class="brush: cpp; gutter: true">QObject::connect(&amp;Отправитель,SIGNAL(mysignal()),&amp;Адресат,SLOT(myslot()));</pre>
<div class="alert alert-info">
<p style="text-align: justify;">В шаблонной версии выглядит так:</p>
<p style="text-align: justify;">bool QObject::connect (const QObject * <i>sender</i>, const char * <i>signal</i>, const QObject * <i>receiver</i>, const char * <i>method</i>, <i>type</i> Qt::ConnectionType = Qt::AutoConnection)</p>
</div>
<p><strong>Для создания связи необходимо прописать:</strong></p>
<ol>
<li>Отправителя и его сигнал.</li>
<li>Получателя и его слот.</li>
<li>А также тип соединения, который зависит от того используете вы соединение в потоке или нет. По умолчанию тип соединения определяется автоматически.</li>
</ol>
<p style="text-align: justify;">Этот <span style="text-decoration: underline;">старый способ</span> соединения использует механизм обработки строк. Если не существует сигнала или слота с данными именами, то соединения не происходит, а в консоль не отсылается сообщение об ошибке. Разъединение происходит при уничтожении объекта автоматически. В редких случаях используется такая форма для отключения сигналов:</p>
<pre class="brush: cpp; gutter: true">QObject::disconnect(&amp;Отправитель,SIGNAL(mysignal()),&amp;Адресат,SLOT(myslot()));</pre>
<div class="alert alert-info">Шаблон: bool QObject::disconnect ( const QObject * <i>sender</i>, const char * <i>signal</i>, const QObject * <i>receiver</i>, const char * <i>method</i> )</div>
<p><strong>2)connect(&amp;Отправитель,&amp;Class_1::mysignal,&amp;Адресат,&amp;Class_2::myslot);</strong></p>
<div class="alert alert-info">Шаблон:connect(sender, &amp;Sender::valueChanged,  receiver, &amp;Receiver::updateValue);</div>
<p><strong>Достоинства:</strong></p>
<ol>
<li>Проверка существования сигналов и слота, типов, или если<code> Q_OBJECT</code> отсутствует(<em>выдаёт ошибки</em>).</li>
<li>Параметр может быть определением типа или с различными спецификаторами пространства имен.</li>
<li>Возможность автоматического приведения типов, если есть неявное преобразование (например, от QString до QVariant)</li>
<li>Возможно соединиться с любой функцией-членом класса(произведённого от QObject),а не только со слотами.</li>
</ol>
<p><strong>Недостатки:</strong></p>
<ol>
<li>   Более сложный синтаксис(Вы должны определить тип своего объекта)</li>
<li>   Очень сложный синтаксис в случаях перегрузок</li>
<li>   Параметры по умолчанию в слоте теперь не поддерживаются.</li>
</ol>
<p><span style="text-decoration: underline;"><strong>Нововведение:</strong> возможность соединения с простой функцией.</span></p>
<p>Благодаря новому синтаксису, появилась возможность соединения с функциями не являющимися слотами. Пример:<strong>connect(sender, &amp;Sender::valueChanged, saveFunction);</strong></p>
<div class="alert alert-warning">При создании такого вида соединения не происходит автоматического разъединения при уничтожении получателя! Это нужно делать вручную.</div>
<p>Такая форма используется для разъединения:</p>
<div class="alert alert-info">Шаблон:QObject::disconnect(sender, &amp;Sender::valueChanged,  receiver, &amp;Receiver::updateValue );</div>
<p><em><strong>Оба способа соединения разрешены</strong></em> для применения в программе. Так-как у них имеются различия нужно выбирать тот способ, который лучше подходит под ваши нужды.</p>
<p style="text-align: justify;"><em>Разберём на примере использование слотов и сигналов в программе.</em></p>
<h4 style="text-align: justify;">Пример:</h4>
<p>Добавьте в созданный на предыдущем уроке <code>"sppstudio"</code> новый подпроект<span style="color: #993300;"> lesson_2</span>(Qt Widget).</p>
<p>Очистите его от посторонних файлов, оставив в нём <span style="color: #993300;">main.cpp</span>.Создайте в нем файлы <span style="color: #993300;">myclass.h</span> и <span style="color: #993300;">myclass.cpp</span>. Давайте придумаем функциональность для нашей программы. Пусть она при нажатии на кнопку создаёт окна и если число созданных окон превысит 5, то она закончит выполнение.</p>
<p>Перед вами реализация её класса:</p>
<pre class="brush: cpp; gutter: true">//myclass.h
#ifndef MYCLASS
#define MYCLASS
#include &lt;QLabel&gt;
#include &lt;QPushButton&gt;
#include &lt;QDialog&gt;
#include &lt;QHBoxLayout&gt;
#include &lt;QDebug&gt;

//отображение числа нажатий
class MyClass:public QObject
{
Q_OBJECT
private:
    QPushButton * butt;
    QHBoxLayout * hbox;
    QWidget *window;
    static int counter;//счетчик объектов
public:
    MyClass();
    ~MyClass()
    {
        qDebug()&lt;&lt;&quot;delete object MyClass&quot;;
        delete butt;
        delete hbox;
        delete window;
    }

private slots:
    void incCounter();//добавляет единицу к counter при вызове
    void newWindow();//создаёт новое окно
signals:
    s_transmitter();//сигнал передатчик
};
#endif // MYCLASS</pre>
<p>В заголовочном файле прописываем слоты, сигнал и члены класса.</p>
<p>Обратите внимания на макросы:</p>
<p><span class="badge">Q_Object</span>  &#8212; нужно прописывать в любом классе использующего свои слоты и сигналы.</p>
<p><span class="badge">private slots:</span> и <span class="badge">signals:</span>  &#8212; здесь собственно они прописываются.</p>
<p>Определения методов у нас находятся в файле <span style="color: #993300;">.cpp</span></p>
<p>Перейдём к его  детальному рассмотрению:</p>
<pre class="brush: cpp; gutter: true">//myclass.cpp
#include &quot;myclass.h&quot;
#include &lt;QString&gt;
#include &lt;QApplication&gt;

MyClass::MyClass()
{
    butt = new QPushButton(&quot; Создать ещё окно &quot;);

    QString str;
    str = &quot;Экземпляр №&quot;+QString::number(counter);

    hbox = new QHBoxLayout;
    hbox-&gt;addWidget(butt);

    connect(butt,SIGNAL(clicked()),this,SLOT(incCounter()));
    connect(this,SIGNAL(s_transmitter()),this,SLOT(newWindow()));
    /*
    *Это старая версия соединения сигнала и слота
    *А ниже распологается новая:
    *connect(butt,&amp;QPushButton::clicked,this,&amp;MyClass::incCounter);
    *Вы можете выбрать эту версию
    *Для этой маленькой программы не будет большой разницы какой тип вы используете
    */

    window = new QWidget;
    window-&gt;setWindowTitle(str);
    window-&gt;setLayout(hbox);
    window-&gt;resize(230,45);
    window-&gt;move(200,80*counter);
    window-&gt;show();
}
void MyClass::incCounter()
{
    ++counter;
    if(counter&gt;5)
    {
        QCoreApplication::quit();
        return;
    }
    emit s_transmitter();
}

void MyClass::newWindow()
{
    MyClass * m = new MyClass();
    m-&gt;setParent(this);
}
int MyClass::counter = 1;</pre>
<p>Со строки 6 начинается описание конструктора <code>MyClass</code>. В нём создаётся окно с кнопкой и соединяются слоты с  сигналами. В 16-17 происходит соединение старого типа. За настройки вида приложения отвечают строки 27-31.</p>
<p>27: Установка названия окна</p>
<p>29: Размеры окна по x и y</p>
<p>30: Перемещает каждое новое окно вниз чтобы не нагромождать их на одном месте.</p>
<p>Последняя строка отвечает за появление окна на дисплее.</p>
<p>Функция <code>incCounter</code> отвечает за инкриминирование счётчика, вызов сигнала(строка 41) и выход из программы(36-40).</p>
<p>Функция <code>newWindow</code> создаёт новое окно и устанавливает ему родителя.Им становится объект у которого была нажата кнопка.</p>
<div class="alert alert-info"> Установка родителя &#8212; это полезная возможность не следить за удалением объектов в динамической памяти, так как класс QObject берёт на себя все обязательства по удалению объектов-потомков при уничтожении родителя.</div>
<pre class="brush: cpp; gutter: true">//main.cpp
#include &lt;QApplication&gt;
#include &quot;myclass.h&quot;
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyClass myclass;
    a.exec();
    return 0;
}</pre>
<p>И наконец <code>main.cpp</code>.</p>
<p>В нём прописывается автоматическая переменная-объект, которая удаляется при завершении программы.</p>
<h4>Резюме:</h4>
<p>Собственно в следующих статьях будет произведён упор не на описании базовых функций, а об использовании полезных особенностей библиотеки на практике. <a href="http://doc.crossplatform.ru/" target="_blank" rel="nofollow">Здесь</a> вы можете найти русский перевод документации по Qt 4.3 – 4.8. Описываются классы библиотеки, основные свойства и инструменты разработки.</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/11167/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Первая программа на Qt:</title>
		<link>http://cppstudio.com/post/11127/</link>
		<comments>http://cppstudio.com/post/11127/#comments</comments>
		<pubDate>Wed, 05 Aug 2015 21:41:08 +0000</pubDate>
		<dc:creator><![CDATA[tenebris]]></dc:creator>
				<category><![CDATA[Библиотека Qt]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=11127</guid>
		<description><![CDATA[Первая программа на Qt: Qt – это мощный инструментарий, имеющий множество способов для воплощения задумок программиста в жизнь. Давайте начнём его освоение с самой первой программы Итак, у вас под рукой имеется среда разработки QtCreator с подключенным к ней компилятором(например MinGW). В среде разработки выбираем Другой проект-&#62; Проект с поддиректориями. Название: cppstudio. Здесь для удобства мы будем хранить все приложения взятые с сайта. Создадим здесь под проект QWidget с название lesson_1 и удаляем в нём файлы mainwindows.h, mainwindows.cpp, &#8230; <a href="http://cppstudio.com/post/11127/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<h3 style="text-align: justify;">Первая программа на Qt:</h3>
<p style="text-align: justify;"><strong>Qt</strong> – это мощный инструментарий, имеющий множество способов для воплощения задумок программиста в жизнь. Давайте начнём его освоение с самой первой программы<br />
Итак, у вас под рукой имеется среда разработки <code>QtCreator</code> с подключенным к ней компилятором(например <code>MinGW</code>). В среде разработки выбираем Другой проект-&gt; Проект с поддиректориями.</p>
<p style="text-align: justify;">Название: <code>cppstudio</code>. Здесь для удобства мы будем хранить все приложения взятые с сайта. Создадим здесь под проект <code>QWidget</code> с название <code>lesson_1</code> и удаляем в нём файлы <code>mainwindows.h</code>, <code>mainwindows.cpp</code>, и форму.</p>
<p style="text-align: justify;">Переписываем код программы печатающей на экран &#171;Привет мир!&#187; в <code>main.cpp</code>:</p>
<pre class="brush: cpp; gutter: true">#include &lt;QApplication&gt;
#include &lt;QHBoxLayout&gt;
#include &lt;QLabel&gt;
#include &lt;QPushButton&gt;

int main(int argc, char *argv[])
{
    QApplication qapp(argc, argv);
    QHBoxLayout * hlayout = new QHBoxLayout;
    QLabel *label = new QLabel(&quot;Привет мир!&quot;);
    QPushButton *butt = new QPushButton(&quot;Exit&quot;);
    QWidget *mainWindow = new QWidget;
    QObject::connect(butt,SIGNAL(clicked()),&amp;qapp,SLOT(quit()));
    hlayout-&gt;addWidget(label);
    hlayout-&gt;addWidget(butt);
    mainWindow-&gt;setLayout(hlayout);
    mainWindow-&gt;show();
    return qapp.exec();
}</pre>
<h5 style="text-align: justify;"><strong>Давайте разберём код программы:</strong></h5>
<p style="text-align: justify;">В<strong> строчках 1-4</strong> идёт подключение нужных заголовочных файлов.<br />
В <code>qt</code> за графический интерфейс пользователя отвечает семейство классов <code>&lt;QWidget&gt;</code>. Так как нам понадобятся виджеты, то в первую очередь прописываем нужные библиотеки(<code>QLabel</code>, <code>QPushButton</code>).</p>
<pre class="brush: cpp; gutter: true">#include &lt;QApplication&gt;
QApplication qapp(argc, argv);</pre>
<p style="text-align: justify;">Одноимённый класс, подключаемый через заголовочный файл <code>QApplication</code> нужен в любом Qt-проекте в единственном экземпляре. Он отвечает за отслеживание событий и сообщений в системе, изменения вида окон приложения и другие полезные функции.</p>
<pre class="brush: cpp; gutter: true">QHBoxLayout * hlayout = new QHBoxLayout;
QLabel *label = new QLabel(&quot;Hello World&quot;);
QPushButton *butt = new QPushButton(&quot;Exit&quot;);
QWidget *mainWindow = new QWidget;</pre>
<h5 style="text-align: justify;">В этой части через динамическую память резервируется место под классы.</h5>
<pre class="brush: cpp; gutter: true">QObject::connect(butt,SIGNAL(clicked()),&amp;qapp,SLOT(quit()));</pre>
<p style="text-align: justify;">Через метод класса <span class="badge">QObjekt::connect(&amp;Отправитель,SIGNAL(сигнал()),получатель,SLOT(слот()))</span> реализуется механизм сигналов и слотов. В данном случае при нажатии кнопки приложения генерируется сигнал <span class="badge badge-inverse">clicked()</span>, который активирует слот<span class="badge"> quit()</span> и приводит к закрытию приложения.</p>
<pre class="brush: cpp; gutter: true">layout-&gt;addWidget(label);
layout-&gt;addWidget(butt);</pre>
<p style="text-align: justify;">Для расположения и компоновки виджетов “в сетке”, горизонтально или вертикально используются классы QHBoxLayout, QGridLayout, QHBoxLayout. Метод-член addWidget добавляет  их в менеджер компоновки.</p>
<pre class="brush: cpp; gutter: true">mainWindow-&gt;setLayout(hlayout);
mainWindow-&gt;show();</pre>
<p style="text-align: justify;">Последние строки устанавливают окну класс компоновки с его виджетами и заставляют его стать видимым.</p>
<p style="text-align: justify;"><strong>В итоге у вас должна получится программа:</strong></p>
<p style="text-align: justify;"><a href="http://cppstudio.com/wp-content/uploads/2015/08/lesson_1.bmp"><img class="alignnone size-full wp-image-11154" src="http://cppstudio.com/wp-content/uploads/2015/08/lesson_1.bmp" alt="lesson_1" width="174" height="81" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/11127/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Введение &#8212; графическая библиотека Qt</title>
		<link>http://cppstudio.com/post/11097/</link>
		<comments>http://cppstudio.com/post/11097/#comments</comments>
		<pubDate>Sat, 11 Jul 2015 11:12:22 +0000</pubDate>
		<dc:creator><![CDATA[tenebris]]></dc:creator>
				<category><![CDATA[Библиотека Qt]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=11097</guid>
		<description><![CDATA[Qt – свободная широко распространённая графическая библиотека C++. Она содержит множество компонентов для поддержки не только графики, но и сети, базы данных и т.д. Общая информация: С начала использования программист получает взаимосвязанный фреймворк. Это даёт возможность при написании большей части программы использовать только встроенные классы и практически полностью отказаться от связи с определённой ОС. Такой подход реализует независимость и свободу разработчика. (Отсутствует необходимость переписывать программу под несколько операционных систем. Алгоритм для Windows может, скомпилирован в &#8230; <a href="http://cppstudio.com/post/11097/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Qt – свободная широко распространённая графическая библиотека C++. Она содержит множество компонентов для поддержки не только графики, но и сети, базы данных и т.д.</p>
<h3 style="text-align: justify;">Общая информация:</h3>
<p style="text-align: justify;">С начала использования программист получает взаимосвязанный фреймворк. Это даёт возможность при написании большей части программы использовать только встроенные классы и практически полностью отказаться от связи с определённой ОС. Такой подход реализует независимость и свободу разработчика.<br />
(Отсутствует необходимость переписывать программу под несколько операционных систем. Алгоритм для Windows может, скомпилирован в том же виде под Linux) .</p>
<h3>Основные инструменты и нововведения</h3>
<h4 style="text-align: justify;">Designer</h4>
<p style="text-align: justify;">С помощью этого средства можно с относительной лёгкостью создавать окна для вашего проекта. Полученный интерфейс сохраняется в файл с расширением <code>.ui</code>, который подключается к создаваемой программе с помощью специальных методов.</p>
<h4 style="text-align: justify;">Сигналы и слоты</h4>
<p style="text-align: justify;">Это главное нововведение по сравнению с другими библиотеками отличается от них большой функциональностью и внедрением новых возможностей. С помощью этого механизма осуществляется  связь между объектами. Сигнал отправляется в слот, если происходит запрограммированное событие. Слот же обязан ответить на все подключённые к нему сигналы. Проще говоря, они представляют собой функции-члены объектов, у которых основное направление задач это оперативное реагирование на действия пользователя.</p>
<h3>Подготовка к работе</h3>
<h4>Установка /IDE</h4>
<p style="text-align: justify;">Собственно для программирования с использованием вам нужно скачать её <a href="http://www.qt.io/ru/download/" target="_blank" rel="nofollow">отсюда</a>. Выберете вариант <code>Community</code>. Далее можно выбрать тип загрузки онлайн-инсталятор или оффлайн-инсталляторы.<br />
Среда разработки <code>Creator</code> включена в стандартный бинарный пакет</p>
<h4>Документация и помощь</h4>
<p style="text-align: justify;">Qt-ом пользуется огромное количество программистов из России. На <a href="http://forum.qt.io/category/27/russian" target="_blank" rel="nofollow">русском форуме</a> можно задать вопросы, касающиеся этого Фреймворка. Встроенная справочная <code>QtAssistant</code>, снабжена подробным описанием способов применения графических возможностей библиотеки на английском языке. Но можно найти и <a href="http://link.ac/4Waf6" target="_blank" rel="nofollow">части перевода документации</a> на русский язык и внедрить их в справочник.</p>
<h4>Новые типы расширений, используемые в проектах Qt:</h4>
<h4><code>.<strong>pro</strong></code><u></u></h4>
<p style="text-align: justify;">Файл с этим расширением хранит основные настройки программы: подключаемые модули, формы, файлы с исходным кодом и заголовочные файлы.</p>
<pre class="brush: cpp; gutter: true">#-------------------------------------------------
#
# Project created by QtCreator 2001-07-08T12:04:54
#
#-------------------------------------------------

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = program_01

TEMPLATE = app

SOURCES += main.cpp\
mywindow.cpp

HEADERS += mywindow.h

FORMS   += mywindow.ui</pre>
<p style="text-align: left;">Так в этом примере проект содержит:</p>
<ul>
<li>Модули: <code>core</code>, <code>gui</code>;</li>
<li>Исходный код в <code>main.cpp</code> и <code>mywindows.cpp</code>;</li>
<li>Формы дизайнера: <code>mywindows.ui</code>;</li>
<li>Заголовочные файл: <code>mywindows.h</code>;</li>
<li>Имя проекта:  <code>program_01</code>;</li>
</ul>
<h4><strong><code>.ui</code></strong></h4>
<p style="text-align: justify;">Это файл формы дизайнера. В неё можно, не выходя из среды разработки, добавлять новые виджеты (кнопки, метки, строки ввода). То есть это даёт возможность быстро создавать пользовательский интерфейс (окна приложений, диалогов, оповещений и т.д.)</p>
<h3>Резюме</h3>
<p>На сегодняшний день эта библиотека представляет собой, инструмент о существовании которого полезно знать, чтобы вести быструю разработку пользовательских приложений. Это мощное средство создания графических интерфейсов может помочь вам в уменьшении требований к адаптации программы под конечную платформу. Что конечно же даёт вам сконцентрироваться на задаче и алгоритмах её решения, а не на проблемах совместимости с операционной системой.</p>
<p><strong>Вот примеры нескольких программ использующие Qt: </strong>Battle.net, Google Earth, Skype, медиапроигрыватель VLC, VirtualBox.</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/11097/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Наследование классов</title>
		<link>http://cppstudio.com/post/10103/</link>
		<comments>http://cppstudio.com/post/10103/#comments</comments>
		<pubDate>Wed, 14 May 2014 11:37:07 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Введение в объектно ориентированное программирование]]></category>
		<category><![CDATA[Язык программирования С++]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=10103</guid>
		<description><![CDATA[Наследование классов &#8212; очень мощная возможность в объектно ориентированном программировании. Оно позволяет создавать производные классы (классы наследники), взяв за основу все методы и элементы базового класса (класса родителя). Таким образом экономится масса времени на написание и отладку кода новой программы. Объекты производного класса  свободно могут использовать всё, что создано и отлажено в базовом классе. При этом, мы можем в производный класс,  дописать необходимый код для усовершенствования программы: добавить новые элементы, методы и т.д.. Базовый класс останется нетронутым. Эту тему &#8230; <a href="http://cppstudio.com/post/10103/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Наследование классов &#8212; очень мощная возможность в объектно ориентированном программировании. Оно позволяет создавать производные классы (классы наследники), взяв за основу все методы и элементы базового класса (класса родителя). Таким образом экономится масса времени на написание и отладку кода новой программы. Объекты производного класса  свободно <span style="line-height: 1.428571429;">могут</span><span style="line-height: 1.428571429;"> использовать всё, что создано и отлажено в базовом классе. При этом, </span><span style="line-height: 1.428571429;">мы можем </span><span style="line-height: 1.428571429;">в производный класс,  дописать необходимый код для усовершенствования программы: добавить новые элементы, методы и т.д.. Базовый класс останется нетронутым. Эту тему вполне возможно освоить новичкам. Необходимо только познакомиться с синтаксисом и некоторыми особенностями. Ниже приведен простой код программы, который мы детально разберем под листингом. В этой программе созданы два класса: базовый &#8212; </span><code>FirstClass</code><span style="line-height: 1.428571429;">  и производный от него </span><code>SecondClass</code><span style="line-height: 1.428571429;">.</span></p>
<p style="text-align: justify;">Пример:</p>
<pre class="no_translate brush: cpp; gutter: true">#include &lt;iostream&gt;
using namespace std;

class FirstClass	// базовый класс
{
protected:			// спецификатор доступа к элементу value
	int value;
public:
	FirstClass() 
	{
		value = 0; 
	}

	FirstClass( int input )	
	{ 
		value = input; 
	}

	void show_value() 
	{
		cout &lt;&lt; value &lt;&lt; endl;
	}
};

class SecondClass : public FirstClass	// производный класс
{
public:
	SecondClass() : FirstClass ()	// конструктор класса SecondClass вызывает конструктор класса FirstClass
	{}

	SecondClass(int inputS) : FirstClass (inputS)	// inputS передается в конструктор с параметром класса FirstClass
	{}

	void ValueSqr () // возводит value в квадрат. Без спецификатора доступа protected эта функция не могла бы изменить значение value
	{
		value *= value;		
	}	
};

int main()
{
    setlocale(LC_ALL, &quot;rus&quot;);

	FirstClass F_object(3);		// объект базового класса
	cout &lt;&lt; &quot;value F_object = &quot;;
	F_object.show_value(); 

	SecondClass S_object(4);	// объект производного класса
	cout &lt;&lt; &quot;value S_object = &quot;;
	S_object.show_value();  // вызов метода базового класса

	S_object.ValueSqr();		// возводим value в квадрат 
	cout &lt;&lt; &quot;квадрат value S_object = &quot;;
	S_object.show_value();

	//F_object.ValueSqr();		// базовый класс не имеет доступа к методам производного класса

	cout &lt;&lt; endl;
	return 0;
}</pre>
<p style="text-align: justify;">Разбирать пример будем по-порядку. Ранее мы работали только со спецификаторами доступа <code>private</code> и  <code>public</code>.  В <strong>строке 6</strong> мы встретили новый для нас спецификатор доступа <code>protected</code>. Он отличается от <code>private</code> тем, что разрешает доступ к элементам базового класса из производных классов. Если бы элемент <code>value</code> находился в поле <code>private</code>, то доступ к нему был бы закрыт и мы бы не могли изменить его значение через объект класса <code>SecondClass</code>, используя функцию <code>ValueSqr()</code> , определённую в <strong>строках 34 &#8212; 37</strong>.</p>
<p style="text-align: justify;">Чтобы было наглядней, отличия спецификаторов доступа можно отобразить в таблице:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="234"></td>
<td valign="top" width="85"><strong>private</strong></td>
<td valign="top" width="85"><strong>protected</strong></td>
<td valign="top" width="76"><strong>public</strong></td>
</tr>
<tr>
<td valign="top" width="234"><strong>Доступ из тела класса</strong></td>
<td style="text-align: justify;" valign="top" width="85"> открыт</td>
<td style="text-align: justify;" valign="top" width="85">  открыт</td>
<td style="text-align: justify;" valign="top" width="76">  открыт</td>
</tr>
<tr>
<td valign="top" width="234"><strong>Доступ из производных классов</strong></td>
<td style="text-align: justify;" valign="top" width="85"> закрыт</td>
<td style="text-align: justify;" valign="top" width="85">  открыт</td>
<td style="text-align: justify;" valign="top" width="76">  открыт</td>
</tr>
<tr>
<td valign="top" width="234"><strong>Доступ из внешних функций и классов</strong></td>
<td style="text-align: justify;" valign="top" width="85"> закрыт</td>
<td style="text-align: justify;" valign="top" width="85"> закрыт</td>
<td style="text-align: justify;" valign="top" width="76">  открыт</td>
</tr>
</tbody>
</table>
<p style="text-align: justify;">Если вы создаёте класс, который в дальнейшем планируете использовать, как базовый, то объявляйте в нём поле <code>protected</code> вместо <code>private</code>. Иначе объекты производного класса не смогут обращаться к элементам базового.</p>
<p style="text-align: justify;">Ниже, в <strong>строках 8 &#8212; 22</strong>, определены методы базового класса. <a href="/post/6964/" target="_blank">Конструктор</a> без параметров <code>FirstClass()</code>, конструктор с параметром <code>FirstClass( int input )</code>  и метод <code>void show_value()</code>, который выводит значение <code>value</code> на экран.</p>
<p style="text-align: justify;">Определение производного находится в <strong>строках 25 &#8212; 38</strong>. Синтаксис наследования такой &#8212; <span class="badge badge-important">class   Имя_Производного_Класса    :    спецификатор доступа    Имя_Базового_Класса   {  } ;</span> Двоеточие <code>:</code>  не путайте с двойным двоеточием <code>::</code> (определение области действия).  Используя этот оператор мы показываем, наследником какого класса является производный класс.</p>
<p style="text-align: justify;">Важной особенностью производного класса, является то, что хоть он и может использовать все методы и элементы полей <code>protected</code> и <code>public</code> базового класса, но он не может обратиться к конструктору с параметрами. Если конструкторы в производном классе не определены, при создании объекта сработает конструктор без аргументов базового класса. А если нам надо сразу при создании объекта производного класса внести данные, то для него необходимо определить свои конструкторы. В нашем примере показано, как же мы всё-таки можем использовать уже готовые конструкторы базового класса, чтобы не набирать код конструкторов снова &#8212; <strong>строки 28 &#8212; 32</strong>. Для этого при определении конструктора производного класса после его имени следует поставить оператор <code>:</code> и  имя конструктора базового класса, который необходимо вызвать, при создании объекта производного класса &#8212; <code>SecondClass() : FirstClass (){}</code>. Тело конструктора оставляем пустым т.к. всю работу проделает конструктор базового класса.  В случае конструктора с параметром, этот параметр мы передаем в конструктор с параметром базового класса <code>SecondClass(int inputS) : FirstClass (inputS){}</code> &#8212; <strong>строка  31</strong>.</p>
<p style="text-align: justify;">В main-функции создаем объекты базового и производного классов &#8212; <code>FirstClass F_object(3);</code> и  <code>SecondClass S_object(4);</code> и отображаем их значения <code>value</code> на экран. Как видите в <strong>строке 50</strong>,  объект производного класса без проблем обращается к методу <code>show_value()</code> базового класса. Так, будто это его собственный метод. Ниже вызываем метод, который возводит значения <code>value</code> производного класса в квадрат. И выводим это изменённое значение на экран. А вот если мы захотим вызвать этот метод &#8212;  <code>F_object.ValueSqr();</code> &#8212;  для объекта базового класса, компилятор нам этого не позволит сделать и выдаст ошибку. Это еще одна важная особенность &#8212; производный класс имеет доступ к базовому классу, а базовый класс, даже &#171;не знает&#187; о существовании производного и не может пользоваться его кодом.</p>
<p> Результат работы программы:</p>
<div class="code_window">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">
<p>value F_object = 3<br />
value S_object = 4<br />
квадрат value S_object = 16</p>
</div>
</div>
<p style="text-align: justify;">В виде списка приведу  основную информацию о наследовании классов, которую важно знать:</p>
<ul>
<li style="text-align: justify;">Наследование &#8212; это определение производного класса, который может обращаться ко всем элементам и методам базового класса за исключением тех, которые находятся в поле <code>private</code>;</li>
<li style="text-align: justify;">Производный класс еще называют потомком или подклассом, а базовый &#8212; родитель или надкласс;</li>
<li style="text-align: justify;">Синтаксис определения производного класса:    <span class="badge badge-important">class   Имя_Производного_Класса    :    спецификатор доступа    Имя_Базового_Класса   { /*код*/ } ; </span></li>
<li style="text-align: justify;">Производный класс имеет доступ ко всем элементам и методам базового класса, а базовый класс может использовать только свои собственные элементы и методы.</li>
<li style="text-align: justify;">В производном классе необходимо явно определять свои конструкторы, деструкторы и <a href="/post/7958/" target="_blank">перегруженные операторы </a>присваивания  из-за  того,  что  они  не  наследуются  от  базового  класса. Но  их  можно вызвать явным образом при определении конструктора, деструктора или перегрузки оператора присваивания производного класса, например таким образом (для конструктора): <span class="badge badge-important">Конструктор_Производного_Класса (/*параметры*/)  :  Конструктор_Базового_Класса ( /*параметры*/) { }</span> .</li>
<li style="text-align: justify;">Еще один важный момент при наследовании &#8212; <a href="/post/406/" target="_blank">перегруженные функции</a>-методы  класса потомка. В данном примере мы его не рассматривали. Но чтобы вы знали, если в  классе родителе и в его классах потомках встречаются методы с одинаковым именем, то для объектов  класса потомка компилятор будет использовать методы именно класса потомка. Перегруженные методы класса потомка, могут вызывать методы класса родителя. В таком случае важно помнить, что необходимо правильно определить область действия с помощью оператора <code>::</code> .Иначе компилятор воспримет это, как вызов функцией самой себя.  Наглядно, если бы мы перегрузили в классе <code>SecondClass</code> функцию <code>show_value()</code> &#8212; это  выглядело бы так:</li>
</ul>
<pre class="no_translate brush: cpp; gutter: true">void show_value() 
{
	if(value != 0) 
		FirstClass :: show_value();
}</pre>
<p style="text-align: justify;">Эта запись указывает компилятору  &#8212; если значение <code>value</code> не равно нулю &#8212; вызвать метод <code>show_value()</code> класса <code>FirstClass</code>. А он в свою очередь, отобразит это значение на экране.</p>
<p style="text-align: justify;">Думаю для первого знакомства с наследованием классов этого достаточно. Это бесспорно классная возможность языка С++. Она помогает экономить массу времени на написание и отладку кода с нуля. Вместо этого мы можем использовать уже готовый и отлаженный код и подстраивать его под новые задачи, которые поставлены перед нами. При этом наша новая программа будет занимать намного меньше строк, что значительно улучшит её читабельность.</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/10103/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Перегрузка операторов в С++ (часть 2)</title>
		<link>http://cppstudio.com/post/10058/</link>
		<comments>http://cppstudio.com/post/10058/#comments</comments>
		<pubDate>Wed, 23 Apr 2014 14:48:51 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Введение в объектно ориентированное программирование]]></category>
		<category><![CDATA[Язык программирования С++]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=10058</guid>
		<description><![CDATA[Эта статья является дополнением к статье «Перегрузка операторов в С++». В ней будет рассмотрена перегрузка операций  =  (присваивание), == (равенство) и [ ] (индексация).  Думаю, новичкам будет полезно попрактиковаться и увидеть некоторые нюансы их перегрузки. Поставим перед собой следующие задачи: создать класс, который будет содержать элементы:  int *numbers &#8212; указатель на массив целых чисел  и sizeOfArray &#8212; размер этого массива; перегрузить оператор [] так, чтобы мы могли из main-функции присваивать значение элементам массива класса.  Например, написав &#8230; <a href="http://cppstudio.com/post/10058/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Эта статья является дополнением к статье <a href="/post/7958/" target="_blank">«Перегрузка операторов в С++»</a>. В ней будет рассмотрена перегрузка операций  <code>=</code>  (присваивание), <code>==</code> (равенство) и <code>[ ]</code> (индексация).  Думаю, новичкам будет полезно попрактиковаться и увидеть некоторые нюансы их перегрузки.</p>
<p style="text-align: justify;">Поставим перед собой следующие задачи:</p>
<ul style="text-align: justify;">
<li>создать класс, который будет содержать элементы:  <code>int *numbers</code> &#8212; указатель на массив целых чисел  и <code>sizeOfArray</code> &#8212; размер этого массива;</li>
<li>перегрузить оператор <code>[]</code> так, чтобы мы могли из <code>main</code>-функции присваивать значение элементам массива класса.  Например, написав выражение <code>Object[0] = 3</code>, значение <code>3</code> запишется в ячейку с индексом <code>0</code> массива <code>int *numbers</code>. Теперь нам не придется определять и вызывать метод, который бы выполнял эту операцию (к примеру: <code>Object.setNumber(0,3);</code> где <code>0</code> – индекс массива а <code>3</code> – то что нужно записать);</li>
<li>перегрузить оператор   <code>==</code>  чтобы можно было сравнить массивы  <code>int *numbers</code>  двух разных объектов класса;</li>
<li>перегрузить оператор  <code>=</code>  так, чтобы записав выражение <code>Object = Object2</code> массив <code>int *numbers</code> объекта <code>Object</code>  стал идентичными массиву объекта  <code>Object2</code> и по количеству ячеек массива и по значениям, которые хранят ячейки массива.</li>
</ul>
<p style="text-align: justify;"> Вот решение:</p>
<pre class="no_translate brush: cpp; gutter: true">#include &lt;iostream&gt;
using namespace std;

class MyArray
{
	int *numbers;
	int sizeOfArray;
public:
	MyArray()		//конструктор без параметров
	{
		sizeOfArray = 0;	
		numbers = 0;
	}
//-----------------------------------------------
	MyArray(int size)		//конструктор с параметрами
	{
		sizeOfArray = size;	
		numbers = new int [sizeOfArray];
		for(int i = 0; i &lt; sizeOfArray; i++)
		{
			numbers[i] = 0;
		}
	}
//-----------------------------------------------
	~MyArray()		//деструктор
	{
		delete [] numbers;
	}
//-----------------------------------------------
	void showData()			//вывод данных массива на экран
	{
		for(int i = 0; i &lt; sizeOfArray; i++)
		{
			cout &lt;&lt; numbers[i] &lt;&lt; &quot; | &quot;;
		}
	cout &lt;&lt; endl &lt;&lt; endl;
	}
//-----------------------------------------------
	// на место вызова [] вернется по ссылке сам объект 
	int &amp;operator[](int j) //перегрузка []		
	{
		return numbers[j];
	}
//-----------------------------------------------

	MyArray&amp; operator=( MyArray &amp;arrInt2 ) //перегрузка оператора присваивания
	{
		delete [] numbers;

		sizeOfArray = arrInt2.sizeOfArray;

		numbers = new int [sizeOfArray];
		for (int i = 0; i &lt; sizeOfArray; i++)
		{
			numbers[i] = arrInt2.numbers[i];
		}

		return *this;
	}
//-----------------------------------------------
	friend bool operator ==( MyArray &amp;arrInt, MyArray &amp;arrInt2 ); //перегрузка ==
};

bool operator == ( MyArray &amp;arrInt, MyArray &amp;arrInt2 ) 
{
	if(arrInt.sizeOfArray != arrInt2.sizeOfArray) //сравниваем размеры массивов объектов
	{
		cout &lt;&lt; &quot;В массивах разное количество элементов\n&quot;;
		return 0;
	}
	else //проверяем равны ли данныев в ячейках массивов
	{		
		for (int i = 0; i &lt; arrInt.sizeOfArray; i++)
		{
			if(arrInt.numbers[i] != arrInt2.numbers[i])
			{
				cout &lt;&lt; &quot;Значения массивов не равны\n&quot;;
				return 0;
			}				
		}	
	}
return 1; 
}

int main()
{
	setlocale(LC_ALL, &quot;rus&quot;);

	MyArray ArrayInt(5);	//создаем объект класса и записываем в него данные
	ArrayInt[0] = 1; //перегруженный []
	ArrayInt[1] = 2;
	ArrayInt[2] = 3;
	ArrayInt[3] = 4;
	ArrayInt[4] = 5;
	cout &lt;&lt; &quot;Массив ArrayInt:  &quot;;
	ArrayInt.showData();	//вывод данных массива на экран

	MyArray ArrayInt2(5); //создаем второй объект класса
	ArrayInt2[0] = 11; //перегруженный []
	ArrayInt2[1] = 22;
	ArrayInt2[2] = 33;
	ArrayInt2[3] = 44;
	ArrayInt2[4] = 55;
	cout &lt;&lt; &quot;Массив ArrayInt2: &quot;;
	ArrayInt2.showData();	//вывод данных массива на экран

	if(ArrayInt == ArrayInt2){ //сравнение двух объектов класса (перегруженный ==)
		cout &lt;&lt; &quot;Массив ArrayInt равен массиву ArrayInt2\n&quot;;
	}
	else {
		ArrayInt = ArrayInt2;
	}
	cout &lt;&lt; &quot;Массив ArrayInt после копирования:  &quot;;
	ArrayInt.showData();

	MyArray ArrayInt3(10); // третий объект класса с массивом из 10 элементов 
	cout &lt;&lt; &quot;Массив ArrayInt3: &quot;;
	ArrayInt3.showData();
	ArrayInt3 = ArrayInt; // копируем массив из ArrayInt в ArrayInt3
	cout &lt;&lt; &quot;Массив ArrayInt3 после копирования: \n&quot;;
	ArrayInt3.showData();

	return 0;
}</pre>
<p style="text-align: justify;">И так &#8212; определяем класс <code>MyArray</code> .  В <strong>строках 9 &#8212; 28</strong> определены <a href="/post/6964/" target="_blank">конструкторы и деструктор</a>.  Тот конструктор, который принимает параметр, будет сразу, при создании <span style="font-size: 14px; line-height: 1.428571429;">объекта класса, </span><span style="font-size: 14px; line-height: 1.428571429;">задавать размер <code>sizeOfArray</code> массива <code>numbers</code>. В <strong>строках 39-43</strong> перегружаем оператор индексирования <code>[]</code>. На место вызова <code>[]</code> вернется по ссылке сам объект и в ячейку его массива <code>numbers</code>  под номером <code>j</code> мы сможем записать целое число.    </span></p>
<p style="text-align: justify;"><span style="font-size: 14px; line-height: 1.428571429;">Ниже в <strong>строках 46 &#8212; 59</strong> перегружаем <code>=</code> (присваивание). Он будет копировать массив одного объекта класса <code>MyArray</code> в массив другого объекта класса. Чтобы это произошло, достаточно будет написать следующее выражение Object = Object2. </span><span style="font-size: 14px; line-height: 1.428571429;">При использовании перегруженного <code>=</code>, вызывается функция  <code>MyArray&amp; operator=( MyArray &amp;arrInt2 )</code> определенная в классе.</span><span style="font-size: 14px; line-height: 1.428571429;"> </span><span style="font-size: 14px; line-height: 1.428571429;"> Первый параметр (объект класса который прописан слева от знака <code>=</code> ) в нее передается неявным образом по <a href="/post/8712/" target="_blank">указателю this</a>, а тот, что в скобках – это тот объект который указан справа от <code>=</code>. Далее выполняется код тела этой функции – определение нового размера массива первого объекта и корректное копирование в него данных элементов массива второго объекта. Возвращает функция указатель на объект <code>return *this;</code> (указатель на самого себя, только уже с внесенными изменениями).</span></p>
<p style="text-align: justify;">Перегрузка <code>==</code> (равенства) у нас определена в <strong>строках 64 &#8212; 83</strong>. А в теле класса прописан ее прототип, как <a href="/post/8423/" target="_blank">дружественной функции</a> класса. Так как оператор <code>==</code> используется для сравнения объектов, то функция его перегрузки  будет возвращать значение типа <code>bool</code>.  Она вернет <code>1</code>, если массивы объектов равны  и по размеру и, по значениям в ячейках массивов. А если нет – вернет <code>0</code> и соответствующее сообщение о том,  что не совпадает.</p>
<p style="text-align: justify;">Ну а в  <code>main()</code> мы просто применяем все перегруженные операторы так, как нам надо для работы.</p>
<p style="text-align: justify;">Результат работы программы:</p>
<div class="code_window">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">
<p>Массив ArrayInt: 1 | 2 | 3 | 4 | 5 |</p>
<p>Массив ArrayInt2: 11 | 22 | 33 | 44 | 55 |</p>
<p>Значения массивов не равны<br />
Массив ArrayInt после копирования: 11 | 22 | 33 | 44 | 55 |</p>
<p>Массив ArrayInt3: 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |</p>
<p>Массив ArrayInt3 после копирования:<br />
11 | 22 | 33 | 44 | 55 |</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/10058/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ввод и вывод текста. Буфер памяти, таймер отсчёта</title>
		<link>http://cppstudio.com/post/9895/</link>
		<comments>http://cppstudio.com/post/9895/#comments</comments>
		<pubDate>Wed, 09 Apr 2014 07:53:13 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Win32 API]]></category>
		<category><![CDATA[Основы Win32 API]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=9895</guid>
		<description><![CDATA[В этой статье речь пойдёт о буфере и о таймере отсчёта. Для начала убедитесь, что Вы разбираетесь в выделении памяти с помощью функции alloc (malloc), free, с помощью операторов new, delete и понимаете функцию преобразованию itoa(). Рассмотрим листинг, представленный ниже: LRESULT CALLBACK WindowProcess(HWND hWindow, UINT uMessage, WPARAM wParameter, LPARAM lParameter) { HDC hDeviceContext; PAINTSTRUCT paintStruct; RECT rectPlace; HFONT hFont; static PTCHAR text; static int size = 0; switch (uMessage) { case WM_CREATE: text=(PTCHAR)GlobalAlloc(GPTR,50000*sizeof(TCHAR)); break; case &#8230; <a href="http://cppstudio.com/post/9895/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p><!--[if gte mso 9]&gt;--></p>
<p style="text-align: justify;">В этой статье речь пойдёт о буфере и о таймере отсчёта.</p>
<p style="text-align: justify;">Для начала убедитесь, что Вы разбираетесь в выделении памяти <a href="http://cppstudio.com/post/9088/" target="_blank">с помощью функции alloc (malloc), free</a>, <a href="http://cppstudio.com/post/9555/" target="_blank">с помощью операторов new, delete</a> и понимаете функцию преобразованию <a href="http://cppstudio.com/post/9952/" target="_blank"><span lang="EN-US">itoa</span>()</a>.</p>
<p style="text-align: justify;">Рассмотрим листинг, представленный ниже:</p>
<pre class="no_translate brush: cpp; gutter: true">LRESULT CALLBACK WindowProcess(HWND hWindow, UINT uMessage, 
			       WPARAM wParameter, LPARAM lParameter)
{
	HDC hDeviceContext;
	PAINTSTRUCT paintStruct;
	RECT rectPlace;
	HFONT hFont;

	static PTCHAR text;
	static int size = 0;

	switch (uMessage)
	{
	case WM_CREATE:
		text=(PTCHAR)GlobalAlloc(GPTR,50000*sizeof(TCHAR));
		break;
	case WM_PAINT: 
		hDeviceContext = BeginPaint(hWindow, &amp;paintStruct);
		GetClientRect(hWindow, &amp;rectPlace); 
		SetTextColor(hDeviceContext, NULL); 
		hFont=CreateFont(50,0,0,0,0,0,0,0,
				 DEFAULT_CHARSET,
				 0,0,0,VARIABLE_PITCH,
				 &quot;Arial Bold&quot;);
		SelectObject(hDeviceContext,hFont);
		if(wParameter != VK_RETURN)
			DrawText(hDeviceContext,
				 (LPCSTR)text,
				 size, &amp;rectPlace,
				 DT_SINGLELINE|DT_CENTER|DT_VCENTER);
		EndPaint(hWindow, &amp;paintStruct);
		break;
	case WM_CHAR:
		switch(wParameter)
		{
		case VK_RETURN:
			size=0;
			break;
		default:
			text[size]=(char)wParameter;
			size++;
			break;
		}
		InvalidateRect(hWindow, NULL, TRUE);
                break;
	case WM_DESTROY:
		PostQuitMessage(NULL);
		GlobalFree((HGLOBAL)text);
		break;
	default:
		return DefWindowProc(hWindow, uMessage, wParameter, lParameter);
	}
	return NULL;
}</pre>
<p>Результат после ввода CppStudio.com будет таким:</p>
<p><!--[if gte mso 9]&gt;--></p>
<p style="text-align: justify;"><a href="http://cppstudio.com/wp-content/uploads/2014/03/Скрин-1.png"><img class="aligncenter  wp-image-9979" alt="Скрин 1" src="http://cppstudio.com/wp-content/uploads/2014/03/Скрин-1.png" width="698" height="360" /></a></p>
<p style="text-align: justify;">Код для функции <code>WinMain</code> не приводится, так как он не менялся с предыдущих уроков.<br />
Данная программа позволяет вводить текст по мере возможности и стирать его клавишей ENTER.</p>
<p style="text-align: justify;">Наверное, Вы заметили, что в программе <a href="http://cppstudio.com/post/9843/" target="_blank">в предыдущем уроке </a>для считывания нажатой клавиши мы использовали message <code>WM_KEYDOWN</code>, а здесь что-то новое &#8212; <code>WM_CHAR</code>.</p>
<p style="text-align: justify;">Отличительная особенность в том, что <code><span lang="EN-US">WM</span>_<span lang="EN-US">KEYDOWN</span></code>нужен для обработки специальных клавиш типа <span lang="EN-US">shift</span>, <span lang="EN-US">ctrl </span>и т.п., а <code><span lang="EN-US">WM</span>_<span lang="EN-US">CHAR</span></code>– отвечает за обработку символов. Обычно они работают вместе для комбинаций клавиш и вызывают друг друга. В этом Вы убедитесь, когда мы будем разбирать работу текстового редактора.</p>
<p style="text-align: justify;">По умолчанию в <span lang="EN-US">MVS </span>используется Юникод. Его отключение производится следующим образом: заходим в свойства проекта</p>
<p><img class="wp-image-9980" alt="Скрин_ЮК_1" src="http://cppstudio.com/wp-content/uploads/2014/03/Скрин_ЮК_1.png" width="620" height="302" /></p>
<p style="text-align: justify;">и отключаем Юникод, нажав &#171;Использовать многобайтовую кодировку&#187;.</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-9981" alt="Скрин_ЮК_2" src="http://cppstudio.com/wp-content/uploads/2014/03/Скрин_ЮК_2.png" width="705" height="323" /></p>
<p style="text-align: justify;">После того, как Вы это сделаете, перед строками не нужно будет писать <span lang="EN-US">L</span>, и представленный код не будет иметь ошибок. По этой причине в программе прошлого урока было не правильное отображение некоторых символов.</p>
<p style="text-align: justify;">Теперь второе отличие: мы можем вводить текст (примерно до 50 кБ), который сохранится в буфере.</p>
<p style="text-align: justify;">Конструкция создания, использования, удаления буфера выглядит так:</p>
<pre class="no_translate brush: cpp; gutter: true">static PTCHAR text;
text=(PTCHAR)GlobalAlloc(GPTR,50000*sizeof(TCHAR));
if()
{
   //....
   // заполняем буфер информацией, используем её, где нам нужно
   //.....
   GlobalFree((HGLOBAL)text);
}</pre>
<p style="text-align: justify;">Она аналогична <code>alloc()</code> и <code>free()</code> и её смысл абсолютно такой же.</p>
<p style="text-align: justify;"><strong>PTCHAR</strong> &#8212; указатель на тип <code>TCHAR</code>.</p>
<p style="text-align: justify;"><strong>GPTR</strong> &#8212; режим выделения памяти (в данном случае фиксированное)<br />
<strong>HGLOBAL</strong> &#8212; тип возвращаемого значения функции <code>GlobalAlloc()</code></p>
<p style="text-align: justify;">Третье достоинство нашей программы &#8212; возможность стирать текст (<strong>строки 36-38</strong>).</p>
<p style="text-align: justify;">В случае нажатия клавиши ENTER – мы делаем окно не действительным с помощью функции <code>InvalidateRect()</code> (<strong>строка 44</strong>), тем самым вызываем сообщение <code>WM_PAINT</code>. В нём прописано, что если параметр <code>wParameter</code> был равен <code>VK_RETURN</code> (то есть ENTER), то мы перерисовываем окно и не вызываем функцию <code>DrawText()</code>.</p>
<p style="text-align: justify;">И, как и обещалось ранее, добавим в функцию таймер и некоторые другие особенности.</p>
<p><!--[if gte mso 9]&gt;--></p>
<pre class="no_translate brush: cpp; gutter: true">static int sec = 0; 
TCHAR workTime[10];
//...
switch (wParameter)
{
case WM_CREATE:
    SetTimer(hWindow, 1, 1000, NULL);
    //...
    SetForegroundWindow(hWindow);
    break;
case WM_CHAR:
    //...
    case VK_BACK: 
       if(size!=0) 
          size--; 
       break;
case WM_TIMER:
    sec++;
    break;
case WM_DESTROY:
    KillTimer(hWindow, 1);
    _itoa(sec, workTime, 10); MessageBox(NULL, (LPCSTR)workTime, &quot;Время работы программы (сек.):&quot;, MB_ICONASTERISK|MB_OK);
    //...
    break;
}</pre>
<p style="text-align: justify;">Добавьте в соответствующие места программы выше представленный код.</p>
<p style="text-align: justify;">Функция<span lang="EN-US"> <code>SetTimer()</code> </span>создаёт таймер<span lang="EN-US">. </span>Первый параметр &#8212; дескриптор окна, третий &#8212; интервал срабатывания <code>WM_TIMER</code> в миллисекундах, второй &#8212; количество вызовов <code>WM_TIMER</code> в заданный интервал времени. Четвёртый параметр &#8212; нам не нужен.</p>
<p style="text-align: justify;">В сообщении <code>WM_TIMER</code> мы увеличиваем <code>sec</code> на единицу.</p>
<p style="text-align: justify;">Функция <code>KillTimer()</code> &#8212; удаляет таймер. Параметры те же, что и в <code>SetTimer()</code>.</p>
<p style="text-align: justify;">Чтобы отобразить время работы программы, в <code>WM_DESTROY</code>мы преобразовываем <code>int</code> в <code>TCHAR</code> массив при помощи функции <code>_itoa</code>, выводим строку на экран, удаляем таймер и освобождаем память, выделенную под буфер.</p>
<p style="text-align: justify;">Функция <code>SetForegroundWindow(HWND)</code> – делает окно активным. Например, если Вы находитесь на сайте CppStudio.com и при этом идёт компиляция данной программы, это окно появится поверх браузера с фокусом для ввода.</p>
<p style="text-align: justify;">Для возможности удаления одного или нескольких символов добавлен обработчик <code>VK_BACK</code>– нажатие клавиши backspace. Если <code>size</code> не равен нулю (то есть не был нажат ENTER), мы уменьшаем его на единицу и последний элемент при обновлении окна не отображается.</p>
<p style="text-align: justify;"><!--[if gte mso 9]&gt;--></p>
<p style="text-align: justify;"><!--[if gte mso 9]&gt;--></p>
<p style="text-align: justify;">В результате, при закрытии окна, мы получим такое сообщение:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-9983" alt="Скрин 2" src="http://cppstudio.com/wp-content/uploads/2014/03/Скрин-2.png" width="232" height="161" /></p>
<p style="text-align: justify;">До встречи в следующем уроке!</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/9895/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Функция itoa</title>
		<link>http://cppstudio.com/post/9952/</link>
		<comments>http://cppstudio.com/post/9952/#comments</comments>
		<pubDate>Mon, 31 Mar 2014 16:05:18 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Без рубрики]]></category>
		<category><![CDATA[Заголовочный файл cstdlib (stdlib.h)]]></category>
		<category><![CDATA[Стандартные заголовочные файлы из Си в С++]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=9952</guid>
		<description><![CDATA[Прототип функции itoa: char *itoa( int value, char * string, int radix ); Заголовочный файл Название Язык stdlib.h С cstdlib С++ Описание Функция itoa преобразует целое число value в строку string в формате radix. К цифрам числа value подбираются ANSI символы типа char и записываются в строку string. Функция имеет неудобство, заключающееся в том, что при числе, имеющем количество цифр, большее, чем размер строки, функция выдаст ошибку. Поэтому нужно устанавливать размер с запасом. Также данная &#8230; <a href="http://cppstudio.com/post/9952/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<h3>Прототип функции itoa:</h3>
<pre class="no_translate brush: cpp; gutter: false">char *itoa( int value, char * string, int radix );</pre>
<h3>Заголовочный файл</h3>
<table class="table table-bordered table-striped table-hover" border="0">
<thead>
<tr>
<th>Название</th>
<th>Язык</th>
</tr>
</thead>
<tbody>
<tr>
<td>stdlib.h</td>
<td>С</td>
</tr>
<tr>
<td>cstdlib</td>
<td>С++</td>
</tr>
</tbody>
</table>
<h3>Описание</h3>
<p style="text-align: justify;">Функция <code>itoa</code> преобразует целое число <code>value</code> в строку <code>string</code> в формате <code>radix</code>. К цифрам числа <code>value</code> подбираются ANSI символы типа <code>char</code> и записываются в строку <code>string</code>.</p>
<p style="text-align: justify;">Функция имеет неудобство, заключающееся в том, что при числе, имеющем количество цифр, большее, чем размер строки, функция выдаст ошибку. Поэтому нужно устанавливать размер с запасом.</p>
<p style="text-align: justify;">Также данная функция поддерживается только Visual Studio и в других IDE не имеет описания.</p>
<h3>Параметры:</h3>
<ul>
<li><b>value</b> &#8212; преобразуемое число</li>
<li><b>string</b> &#8212; строка, в которую преобразуется число</li>
<li><b>radix</b> &#8212; основание степени счисления</li>
</ul>
<h3>Возвращаемое значение</h3>
<p style="text-align: justify;">Функция <code>itoa</code> всегда возвращает указатель на <code>string</code>. Чтобы отследить неправильное преобразование, используйте функцию <code>_itoa_s</code>, описание которой:</p>
<pre class="no_translate brush: cpp; gutter: true">char *_itoa_s( int value, char * string, int size, int radix );</pre>
<p style="text-align: justify;">где <code>size</code> &#8212; размер строки <code>string</code>. Данная функция возвращает ноль, если преобразование проходит успешно.</p>
<h3>Пример: исходный код программы</h3>
<p>Код MVS С++</p>
<pre class="no_translate brush: cpp; gutter: true">#include &quot;stdafx.h&quot;
#include &lt;iostream&gt;
#include &lt;cstdlib&gt;

int main(int argc, char ** argv)
{
        int value;
        char string[6] = &quot;&quot;;
        setlocale(LC_ALL, &quot;Russian&quot;);
        std::cout &lt;&lt; &quot;Введите число: &quot;;
        std::cin &gt;&gt; value;
        itoa(value, string, 10);
        std::cout &lt;&lt; &quot;Введённое число при radix = 10: &quot; &lt;&lt; string &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;Элементы строки: &quot; &lt;&lt; std::endl;
        for( int i = 0; i &lt; 6; i++ )
             std::cout &lt;&lt; string[i];
        std::cout &lt;&lt; &quot;.&quot; &lt;&lt; endl;
        itoa(value, string, 16);
        std::cout &lt;&lt; &quot;Введённое число при radix = 16: &quot; &lt;&lt; string &lt;&lt; std::endl;
        system(&quot;pause&quot;);
        return 0;
}</pre>
<h3>Пример работы программы</h3>
<div class="code_window">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">
<p>Введите число: 12586</p>
<p>Введённое число при radix = 10: 12586</p>
<p>Элементы строки:</p>
<p>12586 .</p>
<p>Введённое число при radix = 16: 312a</p>
<p>Для продолжения нажмите любую клавишу . . .</p>
</div>
</div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/9952/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Обмен содержимым контейнеров map и multimap</title>
		<link>http://cppstudio.com/post/9918/</link>
		<comments>http://cppstudio.com/post/9918/#comments</comments>
		<pubDate>Thu, 27 Mar 2014 20:35:24 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Библиотека стандартных шаблонов (STL)]]></category>
		<category><![CDATA[Контейнер map]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=9918</guid>
		<description><![CDATA[Для того, что бы поменять содержимое контейнеров местами, можно использовать следующий код: map&#60;char,int&#62; MapFirst,MapSecond,temp; temp=MapFirst; MapFirst=MapSecond; MapSecond=temp; Но в С++ предусмотрена для этого специальная функция map::swap(), которая позволяет менять содержимое контейнеров map и multimap местами, сейчас покажу как. #include &#60;iostream&#62; #include &#60;map&#62; using namespace std; int main () { map&#60;char,int&#62; MapFirst; map&#60;char,int&#62; MapSecond; MapFirst[&#039;a&#039;]=1; MapFirst[&#039;b&#039;]=2; MapSecond[&#039;z&#039;]=23; MapSecond[&#039;y&#039;]=22; cout &#60;&#60; &#34;MapFirst keeps before swap: MapSecond keeps before swap:&#34; &#60;&#60; endl; auto itMapFirst=MapFirst.begin(); auto itMapSecond=MapSecond.begin(); for(itMapFirst,itMapSecond; itMapFirst &#8230; <a href="http://cppstudio.com/post/9918/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p>Для того, что бы поменять содержимое контейнеров местами, можно использовать следующий код:</p>
<pre class="no_translate brush: cpp; gutter: true">map&lt;char,int&gt; MapFirst,MapSecond,temp;

temp=MapFirst;
MapFirst=MapSecond;
MapSecond=temp;</pre>
<p>Но в С++ предусмотрена для этого специальная функция <code>map::swap()</code>, которая позволяет менять содержимое контейнеров <code>map</code> и <code>multimap</code> местами, сейчас покажу как.</p>
<pre class="no_translate brush: cpp; gutter: true">#include &lt;iostream&gt;
#include &lt;map&gt;

using namespace std;
int main ()
{
  map&lt;char,int&gt; MapFirst;
  map&lt;char,int&gt; MapSecond;

  MapFirst[&#039;a&#039;]=1;
  MapFirst[&#039;b&#039;]=2;

  MapSecond[&#039;z&#039;]=23;
  MapSecond[&#039;y&#039;]=22;

  cout &lt;&lt; &quot;MapFirst keeps before swap:  MapSecond keeps before swap:&quot; &lt;&lt; endl;
  auto itMapFirst=MapFirst.begin();
  auto itMapSecond=MapSecond.begin();
  for(itMapFirst,itMapSecond; itMapFirst != MapFirst.end(); ++itMapFirst,++itMapSecond)
  {
      cout &lt;&lt; itMapFirst-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapFirst-&gt;second &lt;&lt; &quot;\t\t\t\t\t&quot;
      &lt;&lt; itMapSecond-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapSecond-&gt;second &lt;&lt;endl;
  }

  swap(MapFirst,MapSecond);///обмен 

  cout &lt;&lt; &quot;MapFirst keeps after swap:    MapSecond keeps after swap:&quot; &lt;&lt; endl;
  itMapFirst=MapFirst.begin();
  itMapSecond=MapSecond.begin();
  for(itMapFirst,itMapSecond; itMapFirst != MapFirst.end(); ++itMapFirst,++itMapSecond)
  {
      cout &lt;&lt; itMapFirst-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapFirst-&gt;second &lt;&lt; &quot;\t\t\t\t\t&quot;
      &lt;&lt; itMapSecond-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapSecond-&gt;second &lt;&lt;endl;
  }

  MapFirst.swap(MapSecond);///обмен

  cout &lt;&lt; &quot;MapFirst keeps after anoter swap:    MapSecond keeps after anoter swap:&quot; &lt;&lt; endl;
  itMapFirst=MapFirst.begin();
  itMapSecond=MapSecond.begin();
  for(itMapFirst,itMapSecond; itMapFirst != MapFirst.end(); ++itMapFirst,++itMapSecond)
  {
      cout &lt;&lt; itMapFirst-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapFirst-&gt;second &lt;&lt; &quot;\t\t\t\t\t&quot;
      &lt;&lt; itMapSecond-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapSecond-&gt;second &lt;&lt;endl;
  }

  return 0;
}</pre>
<p>Вывод программы:</p>
<div class="code_window">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">
<p>MapFirst keeps before swap: MapSecond keeps before swap:<br />
a : 1                                  y : 22<br />
b : 2                                  z : 23<br />
MapFirst keeps after swap: MapSecond keeps after swap:<br />
y : 22                                 a : 1<br />
z : 23                                 b : 2<br />
MapFirst keeps after anoter swap: MapSecond keeps after anoter swap:<br />
a : 1                                  y : 22<br />
b : 2                                  z : 23</p>
</div>
</div>
<p>В <strong>строках 10, 11</strong> мы заполняем контейнер <code>MapFirst</code>, в <strong>строках 13,14</strong> контейнер <code>MapSecond</code>.</p>
<p>Обратите внимание на еще один вариант заполнения контейнера <code>map</code>. В квадратных скобках мы указываем наш <code>ключ</code>, а после знака равенства &#8212; <code>значение</code>.</p>
<p>В <strong>строках 19-23,</strong> выводим на экран содержимое наших контейнеров. В <strong>строке 25</strong> происходит смена элементов двух контейнеров. Теперь контейнер <code>MapFirst</code> содержит то, что содержал контейнер <code>MapSecond</code>, а <code>MapSecond</code> содержит значения контейнера <code>MapFirst</code>.</p>
<p><strong>Важно</strong>: функция <code>map::swap()</code> работает только в случае, если контейнеры относятся к одному типу т. е., если вы напишите, что-то вроде этого:</p>
<pre class="no_translate brush: cpp; gutter: true">map&lt;char,int&gt; MapFirst;
map&lt;char,float&gt; MapSecond;</pre>
<p>компилятор выдаст ошибку. Будьте внимательны, не допускайте подобного.</p>
<p>В <strong>строках 30-34</strong> осуществляется вывод на экран. Альтернативный вариант функции <code>map::swap()</code> показан в <strong>строке 36</strong> и вывод в <strong>строках 41-45</strong> показывающий, что функция отработала верно. Для контейнера <code>multimap</code> все работает так же, как и для контейнера <code>map</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/9918/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Контейнер map: функции insert(), emplace(), lower_bound(), upper_bound()</title>
		<link>http://cppstudio.com/post/9833/</link>
		<comments>http://cppstudio.com/post/9833/#comments</comments>
		<pubDate>Thu, 20 Mar 2014 12:34:11 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Библиотека стандартных шаблонов (STL)]]></category>
		<category><![CDATA[Контейнер map]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=9833</guid>
		<description><![CDATA[Поскольку, Вы уже сталкивались с функцией map::insert(), в следующем примере, я покажу, альтернативные варианты добавления элементов в  контейнер multimap и map, например: #include &#60;iostream&#62; #include &#60;map&#62; using namespace std; int main () { multimap&#60;float,string&#62; myMultimapExample; map&#60;string,float&#62; myMapExample; /// первый вариант myMapExample.insert ( pair&#60;string,float&#62;(&#34;Desk&#34;,0.01) ); myMapExample.insert ( pair&#60;string,float&#62;(&#34;Table&#34;,0.02) ); myMultimapExample.insert ( pair&#60;float,string&#62;(0.01,&#34;Desk&#34;) ); myMultimapExample.insert ( pair&#60;float,string&#62;(0.01,&#34;Table&#34;) ); /// второй вариант multimap&#60;float,string&#62;::iterator itMultimapExample = myMultimapExample.begin();///итератор указывает на начало multimap map&#60;string,float&#62;::iterator itMapExample = myMapExample.begin(); myMapExample.insert ( itMapExample, pair&#60;string,float&#62;(&#34;Pencil&#34;,0.03) ); myMultimapExample.insert &#8230; <a href="http://cppstudio.com/post/9833/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Поскольку, Вы уже сталкивались с функцией <code>map::insert()</code>, в следующем примере, я покажу, альтернативные варианты добавления элементов в  контейнер <code>multimap</code> и <code>map</code>, например:</p>
<pre class="no_translate brush: cpp; gutter: true">#include &lt;iostream&gt;
#include &lt;map&gt;

using namespace std;
int main ()
{
  multimap&lt;float,string&gt; myMultimapExample;
  map&lt;string,float&gt; myMapExample;

  /// первый вариант
  myMapExample.insert ( pair&lt;string,float&gt;(&quot;Desk&quot;,0.01) );
  myMapExample.insert ( pair&lt;string,float&gt;(&quot;Table&quot;,0.02) );
  myMultimapExample.insert ( pair&lt;float,string&gt;(0.01,&quot;Desk&quot;) );
  myMultimapExample.insert ( pair&lt;float,string&gt;(0.01,&quot;Table&quot;) );

  /// второй вариант
  multimap&lt;float,string&gt;::iterator itMultimapExample = myMultimapExample.begin();///итератор указывает на начало multimap
  map&lt;string,float&gt;::iterator itMapExample = myMapExample.begin();
  myMapExample.insert ( itMapExample, pair&lt;string,float&gt;(&quot;Pencil&quot;,0.03) );
  myMultimapExample.insert ( itMultimapExample, pair&lt;float,string&gt;(0.03,&quot;Pencil&quot;) );

  /// третий вариант
  map&lt;string,float&gt; myMapExampleDifferent;
  multimap&lt;float,string&gt; myMultimapExampleDifferent;
  myMapExampleDifferent.insert( myMapExample.begin(),myMapExample.find(&quot;Table&quot;) );
  myMultimapExampleDifferent.insert( myMultimapExample.begin(),myMultimapExample.find(0.03) );

  /// вывод на экран map и multimap:
  cout &lt;&lt; &quot;myMapExample: \t\t myMultimapExample:\n&quot;;
  for ( itMapExample = myMapExample.begin(),itMultimapExample = myMultimapExample.begin(); itMapExample != myMapExample.end(); ++itMapExample,++itMultimapExample)
  {
      cout &lt;&lt; itMapExample-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapExample-&gt;second &lt;&lt; &quot;\t\t   &quot; &lt;&lt; itMultimapExample-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMultimapExample-&gt;second &lt;&lt; endl;
  }

  auto itMapExampleDif = myMapExampleDifferent.begin();
  auto itMultimapExampleDif = myMultimapExampleDifferent.begin();
  cout &lt;&lt; &quot;\nmyMapExampleDifferent: \t myMultimapExampleDifferent:\n&quot;;
  for ( itMapExampleDif,itMultimapExampleDif; itMapExampleDif != myMapExampleDifferent.end(); ++itMapExampleDif,++itMultimapExampleDif)
  {
      cout &lt;&lt; itMapExampleDif-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMapExampleDif-&gt;second &lt;&lt; &quot;\t\t    &quot; &lt;&lt; itMultimapExampleDif-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMultimapExampleDif-&gt;second &lt;&lt; &#039;\n&#039;;
  }

  return 0;
}</pre>
<p style="text-align: justify;">Работа программы:</p>
<div class="code_window" style="text-align: justify;">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">myMapExample:            myMultimapExample:</div>
<div class="code_window_content">Desk : 0.01                0.01 : Desk</div>
<div class="code_window_content">Pencil : 0.03              0.01 : Table</div>
<div class="code_window_content">Table : 0.02               0.03 : Pencil</div>
<div class="code_window_content"></div>
<div class="code_window_content"></div>
<div class="code_window_content">myMapExampleDifferent:   myMultimapExampleDifferent:</div>
<div class="code_window_content">Desk : 0.01                 0.01 : Desk</div>
<div class="code_window_content">Pencil : 0.03               0.01 : Table</div>
</div>
<p style="text-align: justify;">Если Вы используете<a href="http://cppstudio.com/post/2705/"> MVS 2013</a> или <a href="http://cppstudio.com/post/2705/">MVS 2012</a>, то не исключено возникновение вот такой ошибки:</p>
<p style="text-align: justify;"><strong>Error C2679: бинарный &#171;&lt;&lt;&#171;: не найден оператор, принимающий правый операнд типа &#171;const std::string&#187; (или приемлемое преобразование отсутствует)</strong></p>
<p style="text-align: justify;">В программе показано три варианта заполнения контейнера <code>multimap</code> и <code>map</code>.</p>
<ul>
<li style="text-align: justify;">Вариант №1 &#8212; или самый распространенный вариант. В <strong>строке 11 и 12</strong> с помощью функции <code>map:: insert()</code>, мы добавляем элементы в <code>map</code>.<a href="http://cppstudio.com/post/6471/"> Функция</a> принимает два аргумента, первый аргумент <code>ключ</code>, у нас это тип <code>string</code>, второй это <code>значение</code>, у нас это <a href="http://cppstudio.com/post/271/">тип</a><code> float</code>. <strong>Строки 13 и 14</strong> идентичны <strong>строками 11 и 12</strong>, но там элементы добавляются в <code>multimap</code>.</li>
<li style="text-align: justify;">Вариант №2 &#8212; с использованием итератора. В <strong>строке 17</strong> создаем итератор<code>itMultimapExample</code>, в <strong>строке 18</strong>, итератор <code>itMapExample</code>. Функции<code>map::insert()</code>, в <strong>строке 19</strong> мы  передаем два аргумента (первым аргументом выступает наш итератор <code>itMapExample</code>, а вторым, пара  <code>ключ</code>, <code>значение</code>). <strong>Строка 20</strong> равносильна <strong>строке 19</strong>,  только там функция <code>map::insert()</code>, применяется к контейнеру <code>multimap</code>. Может возникнуть вопрос, чем первый вариант отличается от второго? Ответ, тем, что нашим итератором мы рекомендуем позицию, с которой следует начинать поиск позиции элемента, который мы хотим вставить.</li>
<li style="text-align: justify;">Вариант №3 &#8212; с использованием функции <a href="http://cppstudio.com/post/9691/">map::find()</a>. В <strong>строке 23,</strong> <strong>24</strong> объявляем еще один  контейнер <code>map</code> и <code>multimap</code>. <strong>Строку 25</strong> можно прочитать так: заполняй контейнер <code>myMapExampleDifferent</code>,  начиная с начала <code>myMapExample</code>, пока в контейнере <code>myMapExample</code> не встретишь ключ <code>Table</code>. Этот ключ не  будет вставлен в <code>myMapExample</code>. <strong>Строка 26</strong> выполняет предыдущее действие, но применительно к  <code>multimap</code> контейнеру. Вывод на экран <code>myMapExample</code> и <code>myMultimapExample</code> осуществляется в <strong>строках 30-33</strong>, а вывод <code>myMapExampleDifferent</code> и <code>myMultimapExampleDifferent</code> <strong>строках 38-41</strong> .</li>
</ul>
<p style="text-align: justify;"><code>Multimap</code> кроме функции <code>map::insert()</code>, поддерживает еще функцию <code>map::emplace()</code>, рассмотрим  пример:</p>
<pre class="no_translate brush: cpp; gutter: true">#include &lt;iostream&gt;
#include &lt;map&gt;

using namespace std;
int main ()
{
  multimap&lt;char,float&gt; mymultimap;
  map&lt;char,float&gt; mymap;

  ///заполняем multimap
  mymultimap.insert( pair&lt;char,float&gt;(&#039;a&#039;,0.1) );
  mymultimap.insert( pair&lt;char,float&gt;(&#039;b&#039;,0.2) );
  mymultimap.insert( pair&lt;char,float&gt;(&#039;d&#039;,0.4) );
  mymultimap.insert( pair&lt;char,float&gt;(&#039;e&#039;,0.5) );

  ///заполняем map
  mymap.insert( pair&lt;char,float&gt;(&#039;f&#039;,5.3) );
  mymap.insert( pair&lt;char,float&gt;(&#039;g&#039;,4.32) );
  mymap.insert( pair&lt;char,float&gt;(&#039;i&#039;,23.41) );
  mymap.insert( pair&lt;char,float&gt;(&#039;r&#039;,6.5) );

  ///вставляем элементы в multimap
  mymultimap.emplace(&#039;c&#039;,0.3);
  mymultimap.emplace(&#039;b&#039;,9.9);
  cout &lt;&lt; &quot;mymultimap have:&quot; &lt;&lt; endl;
  for (auto it = mymultimap.begin(); it != mymultimap.end(); ++it)
  {
      cout &lt;&lt; it-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; it-&gt;second &lt;&lt; endl;
  }

  auto lowerMap=mymap.lower_bound(&#039;g&#039;);/// нижняя граница map
  auto upperMap=mymap.upper_bound(&#039;i&#039;);///верхняя граница map
  auto lowerMultimap=mymultimap.lower_bound(&#039;b&#039;);/// нижняя граница multimap
  auto upperMultimap=mymultimap.upper_bound(&#039;d&#039;);///верхняя граница multimap

  mymultimap.erase(lowerMultimap,upperMultimap);
  mymap.erase(lowerMap,upperMap);
  auto itMultimap = mymultimap.begin();
  auto itMap = mymap.begin();
  cout &lt;&lt; &quot;\nmymultimap have: \t mymap have:&quot; &lt;&lt; endl;
  for (itMultimap,itMap; itMultimap != mymultimap.end(); ++itMultimap,++itMap)
  {
      cout &lt;&lt; itMultimap-&gt;first &lt;&lt; &quot; : &quot; &lt;&lt; itMultimap-&gt;second &lt;&lt; &quot;\t\t  &quot; &lt;&lt; itMap-&gt;first  &lt;&lt; &quot; : &quot; &lt;&lt; itMap-&gt;second &lt;&lt; endl;
  }
  return 0;
}</pre>
<p style="text-align: justify;">Работа программы:</p>
<div class="code_window" style="text-align: justify;">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">mymultimap have:</div>
<div class="code_window_content">a : 0.1</div>
<div class="code_window_content">b : 0.2</div>
<div class="code_window_content">b : 9.9</div>
<div class="code_window_content">c : 0.3</div>
<div class="code_window_content">d : 0.4</div>
<div class="code_window_content">e : 0.5</div>
<div class="code_window_content"></div>
<div class="code_window_content">mymultimap have:         mymap have:</div>
<div class="code_window_content">a : 0.1                  f : 5.3</div>
<div class="code_window_content">e : 0.5                  r : 6.5</div>
</div>
<p style="text-align: justify;">В <strong>строках 11-14</strong> происходит заполнение контейнера <code>multimap</code>, в <strong>строках 17-20</strong> происходит заполнение контейнера <code>map</code>. В <strong>строке 23</strong> встречается функция  <code>map::emplace()</code>, которая равносильна функции <code>map::insert</code>, но ей не нужно, явно, каждый раз,  указывать тип переменной. В <strong>строках 26-29</strong> осуществляет вывод на экран контейнера <code>multimap</code>.  Контейнер <code>map</code> не поддерживает функцию <code>map::emplace()</code>. В <strong>строке 31</strong> мы встречаем функцию <code>map::lower_bound().</code> Эта функция принимает только один аргумент и возвращает первую позицию в которую может быть вставлен этот элемент. С помощью функции  <code>map::lower_bound()</code>, создаем итератор, указывающий на ключ <code>g</code> в контейнере <code>map</code>. В <strong>32 строке</strong> мы встречаем функцию <code>map::upper_bound()</code>, она возвращает последнюю позицию , в которую может быть вставлен элемент. В <strong>строке 32</strong> создаем еще один итератор, но уже с помощью функции <code>map::upper_bound()</code> и указывающий на ключ <code>i</code>. В <strong>строках 33, 34</strong>, выполняется тоже, но с контейнером <code>multimap</code>. Данные итераторы  выступают в роли «границ», где  при помощи <code>map::erase()</code> в <strong>строке 38, 39</strong>, мы очищаем оба  контейнера (границы контейнеров, тоже стираются). Что осталось в контейнерах, показано в  <strong>строках 43-46</strong>, где осуществляется вывод на экран.</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/9833/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Конструктор копирования в С++</title>
		<link>http://cppstudio.com/post/9903/</link>
		<comments>http://cppstudio.com/post/9903/#comments</comments>
		<pubDate>Wed, 19 Mar 2014 16:53:32 +0000</pubDate>
		<dc:creator><![CDATA[Marienko L.]]></dc:creator>
				<category><![CDATA[Введение в объектно ориентированное программирование]]></category>
		<category><![CDATA[Язык программирования С++]]></category>

		<guid isPermaLink="false">http://cppstudio.com/?p=9903</guid>
		<description><![CDATA[Думаю, главный вопрос, при изучении любой темы по программированию – Зачем?  И на него надо отвечать в первую очередь, а потом уже показывать, как и когда надо применять  те или иные инструменты программирования. Конструктор копирования нужен нам для того, чтобы создавать «реальные» копии объектов класса, а не побитовую копию объекта. Иногда это принципиально важно. Такую «реальную» копию объекта надо создавать в нескольких случаях: когда мы передаем объект в какую-либо функцию в виде параметра; когда какая-либо &#8230; <a href="http://cppstudio.com/post/9903/">Читать далее</a>]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Думаю, главный вопрос, при изучении любой темы по программированию – Зачем?  И на него надо отвечать в первую очередь, а потом уже показывать, как и когда надо применять  те или иные инструменты программирования.</p>
<p style="text-align: justify;">Конструктор копирования нужен нам для того, чтобы создавать «реальные» копии объектов класса, а не побитовую копию объекта. Иногда это принципиально важно. Такую «реальную» копию объекта надо создавать в нескольких случаях:</p>
<ul style="text-align: justify;">
<li>когда мы передаем объект в какую-либо функцию в виде параметра;</li>
<li>когда какая-либо функция должна вернуть объект класса в результате своей работы;</li>
<li>когда мы в главной функции один объект класса инициализируем другим объектом класса.</li>
</ul>
<p style="text-align: justify;">Например, мы передаем объект в функцию в виде параметра. Функция будет работать не с самим переданным объектом, а с его побитовой копией. Допустим в <a href="/post/6964/" target="_blank">конструкторе класса</a>, при создании объекта, выделяется определенный объем памяти, а деструктор класса эту память освобождает. Указатель побитовой копии объекта будет хранить тот же адрес памяти, что и оригинальный объект. И, когда при завершении работы функции и уничтожении побитовой  копии объекта, сработает деструктор, он обязательно освободит память,  которая была занята объектом-оригиналом. В придачу, еще и при завершении работы программы, деструктор сработает повторно и попытается еще раз освободить этот объем памяти, что неизбежно приведет к ошибкам программы. Та же участь постигнет и память, выделенную для указателя объекта, если будет удаляться побитовая копия возвращаемого функцией объекта, и побитовая копия при инициализации объекта класса другим объектом.</p>
<p style="text-align: justify;">Чтобы избежать этих проблем и ошибок существует конструктор копирования. Его работа заключается в том, чтобы создать реальную копию объекта со своей личной выделенной динамической памятью. Синтаксис конструктора копирования следующий:</p>
<pre class="no_translate brush: cpp; gutter: true">имяКласса (const имяКласса &amp; object)
{
    //код конструктора копирования
}</pre>
<p style="text-align: justify;">Рассмотрим простой пример. В нем создадим класс, который будет содержать обычный конструктор, конструктор копирования и деструктор. В этом примере будут описаны все три случая для которых надо применять конструктор копирования.  Для того, чтобы пример не был слишком большим, мы не будем заставлять конструкторы выделять память, а деструктор освобождать память. Пропишем в них только вывод определенного сообщения на экран. Таким образом, можно будет посмотреть, сколько раз сработают конструкторы и деструктор. Как вы понимаете, если бы деструктор освобождал память, то количество его вызовов не должно превышать количество вызовов конструкторов.</p>
<p style="text-align: justify;">Пример:</p>
<pre class="no_translate brush: cpp; gutter: true">#include &lt;iostream&gt;
using namespace std;

class SomeClass
{	
	int *ptr; // указатель на какой-либо участок памяти
public:	

	SomeClass() //  конструктор
	{
		cout &lt;&lt; &quot;\nОбычный конструктор\n&quot;;
	}
	SomeClass(const SomeClass &amp;obj)
	{		
		cout &lt;&lt; &quot;\nКонструктор копирования\n&quot;;
	}
	~SomeClass()	
	{
		cout &lt;&lt; &quot;\nДестркуктор\n&quot;;
	}
};
	void funcShow(SomeClass object) 
	{
		cout &lt;&lt; &quot;\nФункция принимает объект, как параметр\n&quot;;
	}

	SomeClass funcReturnObject()
	{	
		SomeClass object;		
		cout &lt;&lt;	&quot;\nФункция возвращает объект\n&quot;;
		return object;
	}

int main()
{
	setlocale(LC_ALL,&quot;rus&quot;);

	cout &lt;&lt; &quot;1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n&quot;;
	SomeClass obj1; // создаем объект класса

	cout &lt;&lt; &quot;2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n&quot;;
	funcShow(obj1); // передаем объект в функцию

	cout &lt;&lt; &quot;3 - 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n&quot;;
	funcReturnObject(); // эта функция возвращает объект

	cout &lt;&lt; &quot;5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n&quot;;
	SomeClass obj2 = obj1;	// инициализация объекта при создании

}</pre>
<p style="text-align: justify;">В <strong>строках 4 &#8212; 21</strong> определен класс. Обычный конструктор, <strong>строки 9 &#8212; 12</strong>, будет автоматически вызваться при создании новых объектов класса. А конструктор копирования, <strong>строки 13 &#8212; 16</strong>, будет автоматически вызваться при создании копии объекта. Деструктор, <strong>строки 17 &#8212; 20</strong>, вызывается всякий раз когда удаляется либо объект, либо его копия. Ниже определены две функции <code>funcShow()</code> и <code>funcReturnObject()</code>. Первая принимает объект в виде параметра, вторая при вызове во-первых создает новый объект (тут сработает обычный конструктор), а во-вторых возвращает объект (тут сработает конструктор копирования т.к. при возврате объекта из функции создается его временная копия).</p>
<p style="text-align: justify;">Вот какую картинку мы увидим при запуске программы:</p>
<div class="code_window">
<div class="code_window_title">CppStudio.com</div>
<div class="code_window_content">
<p>1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>Обычный конструктор<br />
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>Конструктор копирования</p>
<p>Функция принимает объект, как параметр</p>
<p>Дестркуктор<br />
3 &#8212; 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>Обычный конструктор</p>
<p>Функция возвращает объект</p>
<p>Конструктор копирования</p>
<p>Дестркуктор</p>
<p>Дестркуктор<br />
5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>Конструктор копирования</p>
<p>Дестркуктор</p>
<p>Дестркуктор<br />
Для продолжения нажмите любую клавишу . . .</p>
</div>
</div>
<p style="text-align: justify;">Пойдем по порядку. В <strong>первом блоке</strong> сработал обычный конструктор &#8212; это произошло при создании объекта класса <code>obj1</code>. <strong>Второй блок</strong> отображает работу функции <code>funcShow()</code>. Так как при передаче объекта в функцию создается его копия и сработал конструктор копирования. А при завершении работы функции эта копия уничтожается и срабатывает деструктор. <strong>Блок 3 &#8212; 4</strong> показывает, что при создании нового объекта в функции <code>funcReturnObject()</code> сработал обычный конструктор, а при возврате объекта &#8212; конструктор копирования. Деструктор, как положено отработал дважды &#8212; для оригинала объекта и для копии. И наконец в <strong>пятом блоке</strong> срабатывает конструктор копирования при инициализации нового объекта класса. Затем дважды деструктор  &#8212; один уничтожает копию объекта пятого блока, второй уничтожает объект из первого блока. Ну как-то так. В итоге количество вызовов деструктора совпадает с вызовами конструкторов.</p>
<p style="text-align: justify;">А теперь попробуйте закомментировать конструктор копирования в определении класса и запустите программу.  Вы увидите, что конструктор сработает только дважды, а деструктор, рад стараться, отработает пять раз. И если бы он освобождал память &#8212; это неизбежно  привело бы к ошибке программы.</p>
]]></content:encoded>
			<wfw:commentRss>http://cppstudio.com/post/9903/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
