2016-03-08 2 views
7

В течение моего одного года программирования Qt я много узнал о сигналах и слотах. Но не хватает ...Публичные функции против общедоступных слотов

http://doc.qt.io/qt-5/signalsandslots.html

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

Итак ... Есть ли какая-либо причина не объявлять каждую функцию в классе, который наследуется от QObject, как слот, нужно ли это будет один или нет?

В приведенной выше ссылке, они дают пример:

Небольшой QObject основе класс может читать:

#include <QObject> 

class Counter : public QObject 
{ 
    Q_OBJECT 

public: 
    Counter() { m_value = 0; } 

    int value() const { return m_value; } 

public slots: 
    void setValue(int value); 

signals: 
    void valueChanged(int newValue); 

private: 
    int m_value; 
}; 

Почему определить функцию value() как простая функция и не слот? Были ли какие-либо отрицательные результаты, если бы они сделали это слотом?

ответ

12

В прежние времена у вас не было выбора, кроме как использовать слоты, если вы хотите подключиться к сигналам. Это уже не так в Qt 5, где можно подключать обычные функции-члены или даже бесплатные функции или лямбды.

Объявление регистров слота, которые функционируют в метаданных этого конкретного объекта, что делает его доступным для всех функций Qt, которые зависят от метаобъекта. Помимо этого, это регулярная функция-член, как указано в документации. В самой функции слота нет ничего особенного, разница в генерации метаданных для него в метаобъекте.

Это означает, что объявление слотов происходит за небольшую плату, хотя и небольшую, как во время компиляции, так и в исполняемом размере. Я бы сказал, что это излишне, чтобы все ваши публичные функции были слотами. Было бы более эффективно использовать слоты, когда вам действительно нужны слоты, если они не могут работать с обычной функцией, сделать это слотом.

Также обратите внимание, что почти во всех случаях сигналы объявляются с типом возврата void. Это связано с типичным случаем использования сигналов - они часто могут передавать параметр, но редко возвращают что-либо. Несмотря на то, что можно вернуть значение через сигнал, подключенный к слоту, это используется крайне редко. Поэтому не имеет смысла объявлять функцию, которая возвращает что-то в качестве слота, на который вы собираетесь подключиться, поскольку сам факт, что он возвращает значение, означает, что он, скорее всего, не будет использоваться в типичном контексте сигнала/слота. Вот почему геттер не является слотом в этом примере. Setter как слот является избыточным в Qt 5 и, вероятно, является продуктом этого примера кода, относящегося к Qt 4.

Наконец, разделение слотов из обычных публичных функций - хороший способ проиллюстрировать намерение или «API "этого класса, если хотите.Например, я чаще использую слоты при расширении QML, поэтому мне не нужно отмечать каждую функцию явно как invokable - в отличие от сценария, упомянутого в предыдущем параграфе, такие слоты часто возвращают материал, но они действительно не используются в соединениях. Таким образом, я получаю четкий обзор дизайна интерфейса, который предоставляет класс.

-1

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

Кроме того, слоты работают в цикле событий. Это зависит от вашего кода, если это намеренно или нет.

+1

Этот ответ не имеет ни малейшего смысла, и, похоже, даже не затрагивает вопрос. – MrEricSir

+0

Можете ли вы использовать возвращаемые значения в слотах? Или даже правильно получить значение ссылочного параметра? – SuperFliege

+1

@SuperFliege - слот - это просто функция, он будет работать точно так же, как функция. Многопоточность и время жизни объекта - совершенно другое дело, и влияют на регулярные функции так же сильно, как и на слоты. – dtech

2

В дополнение к ответу ddriver, который является лучшим/правильным ответом (+1 там), я также хотел бы утверждать, что ввести в заблуждение все функции-члены в качестве публичных слотов. Они, как вы определяете функции (private/public/slots и т. Д.), Влияют на воспринимаемое использование класса.

Что я имею в виду, это ... вы можете утверждать, что все функции должны быть общедоступными (или общедоступными слотами), а затем это охватывает все случаи. Однако это может смутить будущего пользователя вашего класса. Считайте, что int value() является общедоступным слотом (его не лучшим примером), кто-то может попытаться использовать его как один, но сама функция имеет возвращаемое значение, которое на самом деле не имеет смысла для слота. Это имеет смысл для нормальной функции-члена, где (как обычный вызов функции) можно получить обратное значение.

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

Я уверен, что это имя для этого правила эмпирическое, так что вы можете посмотреть его на какой-то метод кодирования сайта, но я не могу вспомнить :(

редактировать

Еще одним незначительным примером является автоматическое завершение ... если все ваши функции являются слотами, тогда, когда вы делаете свой connect(this, myClass::mySignal, &someOtherClass, SomeOtherClass::<auto complete options>);, ваш список вариантов автоматического завершения может быть длинным и неясным, что это такое. Если у вас есть только несколько конкретных членов, которые являются слотами то его легче узнать, что выбрать.

+1

Термин, который вы искали, - это инкапсуляция. – thuga

+0

@thuga - Да, инкапсуляция определенно является предметом ... но я уверен, что есть какое-то «название правила» для хранения всего минимально ограниченного .... может быть, это просто «правила инкапсуляции»?: o thanks:) –

+0

Единственное, что я бы добавил к этому ответу, это то, что общедоступные слоты Q_INVOKABLE, и вы можете не хотеть, чтобы все ваши общедоступные методы были доступны из контекста QML. – MrEricSir

2

Ссылка на enca psulation из ответа code_fodder, следует отметить, что действительно нет такой вещи, как частный слот.

Например:

class MyClass : public QObject 
{ 
    Q_OBJECT 
public: 
    MyClass() 
     :QObject(NULL) {} 

private slots: 
    void Hello() { qDebug("Hello World\n"); } 
}; 

#include "main.moc" 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    MyClass* cls = new MyClass; 
    QMetaObject::invokeMethod(cls, "Hello"); 

    return a.exec(); 
} 

Как мы можем видеть здесь, вызывая функцию Hello успешна вне класса.

+0

Это тоже работает для соединений? BTW ответственность за возможность вызова частных функций полностью зависит от Qt, проверка доступа отсутствует. Частные слоты очень реальны, хотя даже если они не соблюдаются метасистемой :) – dtech

+0

Да, если вы подключаетесь через старый метод подключения (pre Qt 5), используя макросы SIGNAL, SLOT. Например, с QTimer * connect (pTimer, SIGNAL (timeout()), cls, SLOT (Hello())); * – TheDarkKnight

+1

@ TheDarkKnight - это действительно интересное наблюдение (+1 для совместного использования). Я всегда использую частные слоты при настройке внутреннего соединения внутри одного и того же класса и публичных в противном случае .... но я никогда не думал проверять (или замечать), что Qt не препятствует видимости частного слота! - все равно это не изменит способ, которым я их определяю, потому что даже если Qt является мягким (или просто неправильно здесь), мне не нравится быть:) –

0

Другой вариант использования, когда вы не хотите, чтобы все методы были слотами, - это когда вы размещаете объекты на JavaScript через Qt's WebKit Bridge: все общедоступные слоты являются invocable из JavaScript.

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

+0

Основная причина моего вопроса состояла в том, что я должен подвергать объекты JavaScript, и люди, которые используют этот конкретный аспект моего приложения, очень рады запросить, что почти каждая функция может быть слотом. Я пытаюсь это ограничить ... но мне нужна причина. Для функций, возвращающих значение, функции могут стать invokable из JavaScript, сделав их 'Q_PROPERTY'. – Thalia