Разделы инструкций

В сети

Пользователей: 122
Из них просматривают:
Аналоги: 51. Видео: 2. Даташиты: 26. Инструкции: 7. Новости: 21. Остальное: 1. Ошибки: 2. Программы: 2. Производители: 2. Расчёты: 1. Форум: 6. Чат: 1.
Участников: 3
Гостей: 119

Google , wolf170571 , Яндекс , далее...
Рекорд 2375 человек онлайн установлен 26.12.2015.

Партнёры


Партнёры

Новые объявления

Оглавление

Механизм сигналов и слотов

Элементы графического интерфейса определённым образом реагируют на действия пользователя и посылают сообщения. Существует несколько вариантов такого решения.

Старая концепция функций обратного вызова (cakkback functions), лежащая в основе X Window, основана на использовании обычных функций, которые должны вызываться в результате действий пользователя. Применение такой концепции значительно усложняет исходный код программы, делая его менее понятным. Кроме того, отсутствует возможность производить проверку типов возвращаемых значений, потому что во всех случаях возвращается указатель на void. Например, для того чтобы сопоставить код с кнопкой, необходимо передать в функцию указатель на кнопку. Если пользователь нажимает на кнопку, функция будет вызвана. Сами библиотеки не проверяют, были ли аргументы, переданные в функцию, требуемого типа, а это часто является причиной сбоев. Другой недостаток функций обратного вызова заключается в том, что элементы графического интерфейса пользователя тесно связаны с функциональными частями программы и это, в свою очередь, заметно усложняет разработку классов независимо друг от друга. Одним из ярких представителей этой концепции является Motif.

Важно помнить, что Motif и Windows API предназначены для процедурного программирования, и с реализацией объектно-ориентированных проектов, наверняка, появятся трудности.

Для программирования ОС Windows существуют специальные библиотеки классов C++, облегчающие программирование для этой операционной системы. Самой популярной библиотекой является Microsoft Foundation Classes (MFC). Её можно, с большой натяжкой, назвать объектно-ориентированной, так как она создавалась людьми, не подозревающими о существовании самых элементарных принципов объектно-ориентированного подхода. Одна из самых фундаментальных заповедей объектно-ориентированного подхода – это инкапсуляция, которая запрещает оставлять атрибуты классов незащищёнными (ведь тогда объекты могут читать и изменять данные без ведома объекта-владельца), но, несмотря на это, во многих MFC-классах это требование не соблюдено. Сама библиотека MFC является надстройкой, предоставляющей доступ к функциям Windows, реализованным на языке C, что заставляет разработчиков время от времени использовать устаревшие структуры, не вписывающиеся в рамки концепции объектно-ориентированного подхода. Интересно также отметить, что сама Microsoft для реализации широко известной программы Microsoft Word не исользует MFC вообще.

При использовании MFC для связей сообщения и методы обработки используются специальные макросы – так называемые карты сообщений (листинг 2.3). Они очень сильно загромождают исходный код программы, заметно снижая её читаемость.

// Листинг 2.3. Отрывок программы, реалиованной с помощью MFC
class CPhotoStyletApp : publiv CWinApp {
public:
    CPhotoStylerApp();
public:
    virtual BOOL InitInstance();
    afx_msg void OnAppAbout();
    afx_msg void OnFileNew();
    DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CPhotoStyleApp, CWinApp)
        ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
        ON_COMMAND(ID_FILE_NEW, OnFileNew)
        ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
        ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
        ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()

Конструкции, подобные показанной в листинге 2.3, очень неудобны для человеческого восприятия и приводят в замешательство при проведении анализа кода программы. Пусть многие рассказывают об удобстве использования средств для автоматического создания подобного кода, но созданы они были не от хорошей жизни. Так, непродуманность самой библиотеки вынуждает разработчика при внесении незначительных изменений модифицировать код самой программы сразу в нескольких местах. Например, для того чтобы добавить в диалоговое окно текстовое поле, необходимо провести целый ряд операций. Во-первых, нужно создать в классе диалога атрибут, предназначенный для хранения значений, вводимых в текстовое поле. Во-вторых, надо задать идентификатор ресурса текстового поля. В-третьих, поставить идентификатор ресурса и атрибут в методе DoDataExchange() в соответствие друг с другом при помощи метода DDC_Text(), после чего будет осуществляться обмен данными между текстовым полем и атрибутом. В-четвёртых, этим обменом необходимо управлять, передавая в методе UpdateData() значения булевого типа true или false. И лишь с помощью средств автоматического создания кода можно, частично, избавиться от этой проблемы, заставив произвести эти изменения за вас и получив взамен другие недостатки, например, дополнительное засорение кода программы ненужной информаций и возможное несовпадение созданного кода с утверждёнными для проекта требованиями для форматирования и нотации (если не используется венгерская нотация). Я не противник обоснованного применения подобного рода средств, но, по моему мнению, они не должны создаваться как средство устранения изъянов плохого дизайнера самой библиотеки.

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

Проблема расширения языка C++ решена в Qt с помощью специального процессора MOC. Он анализирует классы на наличие специального макроса Q_OBJECT в их определении и внедряет в отдельный файл всю необходимую дополнительную информацию. Это происходит автоматически, без непосредственного участия разработчика. Подобная операция автоматического создания кода не противоречит привычному процессу программирования на C++, ведь стандартный препроцессор перед компиляцией самой программы тоже создаёт промежуточный код, содержащий исполненные команды препроцессора. Подобным образом действует и MOC, записывая всю необходимую дополнительную информацию в отдельный файл, содержимое которого может быть проигнорировано. Макрос Q_OBJECT должен располагаться сразу на следующей строке после ключевого слова class с определением имени класса. Очень важно помнить, что после макроса не должно стоять точки с запятой. Внедрять макрос в определение класса имеет смысл в тех случаях, когда созданный класс использует механизм сигналов и слотов, или если ему необходима информация о свойствах.

Механизм сигналов и слотов полностью замещает старую модель функций обратного вызова, он очень гибок и полностью объектно-ориентирован. Сигналы и слоты – это краеугольный концепт программирования с использованием Qt, позволяющий соединить вместе несвязанные друг с другом объекты. Каждый унаследованный от QObject класс способен высылать и получать сигналы. Эта особенность идеально вписывается в концепцию объектной ориентации и не противоречит человеческому восприятию. Представьте себе ситуацию: у вас звонит телефон, и вы реагируете на это снятием трубки. На языке сигналов и слотов подобную ситуацию можно описать следующим образом: объект «телефон» выслал сигнал «звонок», на который объект «человек» отреагировал «снятием трубки».

Использование механизма сигналов и слотов даёт программисту следующие преимущества:

  • каждый класс, унаследованный от QObject, может имет любое количество сигналов и слотов;
  • сообщения, посылаемые посредством сигналов, могут иметь множество аргументов любого типа;
  • сигнал можно соединять с различным количеством слотов. Высылаемый сигнал поступит ко всем подсоединённым слотам;
  • слот может принимать сообщения от многих сигналов, принадлежащих разным объектам;
  • соединение сигналов и слотов можно производить в любой точке приложения;
  • сигналы и слоты являются механизмами, обеспечивающими связь между объектами. Более того, эта связь может выполняться между объектами, которые находятся в различных потоках (см. главу 39);
  • при уничтожении объекта происходит автоматическое разъединение всех сигнально-слотовых связей. Это гарантирует, что сигналы не будут высылаться к несуществующим объектам.

Нельзя не упомянуть и о недостатках, связанных с применением сигналов и слотов:

  • сигналы и слоты не являются частью языка C++, поэтому требуется запуск дополнительного препроцессора перед компиляцией программы;
  • отсылка сигналов происходит немного медленее, чем обычный вызов функций, который производится при использовании механизма функций обратного вызова;
  • существует необходимость в наследовании класса QObject;
  • в процессе компиляции не производится никаких проверок: имеется ли сигнал или слот в соответствующих классах или нет; совместимы ли сигнал и слот друг с другом и могут ли они быть соединены в месте. Об ошибке можно будет узнать лишь тогда, когда приложение будет запущено. Вся эта информация выводится на консоль, поэтому для того чтобы увидеть её в Windows, в проектном файле (см. главу 3) необходимо добавить в секции CONFIG опцию console (для Linux никаких дополнительных изменений проектного файла не требуется).

222

Комментарии принадлежат их авторам. Мы не несем ответственности за их содержание.
Отправитель Нити

Разное

Щуп станет универсальным, если с обратной стороны его на коротком проводе припаять"крокодил" в резиновом чехле.

Интересно

Если на шприц отсоса припоя надеть отрезок силиконовой трубки.

Похожие инструкции