Qt „Private Slots”: co to jest?


83

Rozumiem, jak go używać, ale przeszkadza mi jego składnia. Co robi "prywatne automaty:"?

Nigdy wcześniej nie widziałem czegoś pomiędzy prywatnym słowem kluczowym a: w definicji klasy. Czy dzieje się tutaj jakaś fantazyjna magia C ++?

A tutaj przykład:

 #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);

 ...

3
To nie jest standardowy C ++, to konstrukcja QT. Wyszukaj sygnały i sloty QT .
Alok Zapisz

1
Podczas kompilowania jako C ++ slotsjest definiowane jako #define slots. Podczas kompilacji przy użyciu Qt MOC generuje kod dla kompilatora C ++.
dalle

2
lol było to jeszcze trudniejsze do zrozumienia, ponieważ od tak dawna nie używałem C ++, myślałem, że dodali coś nowego
dtc

Odpowiedzi:


57

Sloty są rozszerzeniem C ++ specyficznym dla Qt. Kompiluje się dopiero po wysłaniu kodu przez preprocesor Qt, Meta-Object Compiler (moc). Zobacz http://doc.qt.io/qt-5/moc.html dokumentację .

Edycja: jak podkreśla Frank, moc jest wymagana tylko do łączenia. Dodatkowe słowa kluczowe są #definowane za pomocą standardowego preprocesora.


Dzięki, preprocesor Qt jest tym, czego mi brakowało w moim mentalnym modelu tego, co się działo.
Justin,

16
Niepoprawnie, kod kompiluje się cały czas, ponieważ „sygnały” i „sloty” są pustymi definicjami, więc kompilator nigdy ich nie widzi. Te makra są wskazówkami do funkcji moc, która generuje dodatkowy kod. Oryginalne pliki .h i .cpp nie są zmieniane i kompilują się bez problemu. To, co mogłoby się nie udać, to linkowanie, ponieważ w innym przypadku brakuje definicji wygenerowanych przez moc (definicje sygnałów, metaobiekty itp.).
Frank Osterfeld,

1
Czy slotssłowo kluczowe jest potrzebne? Próbowałem skompilować / połączyć kilka małych programów Qt, które wywołują sloty bez slotssłowa kluczowego i zbudowały się dobrze. Moje eksperymenty pokazują, że: signals:jest zdecydowanie konieczne, slotsmoże być niepotrzebne i emitwydaje się niepotrzebne, jak czytałem gdzie indziej.
It's Your App LLC

2
slotsnie jest konieczne w Qt5. Qt zaktualizowało connect()składnię, aby umożliwić podłączenie sygnału do dowolnej funkcji, w tym lambd. Z tego powodu slotsnie jest konieczne. Jednak slotssłowo kluczowe nadal wpływa na sposób QMetaObjectbudowania obiektu. moc(inaczej „kompilator metaobiektów”) nie rozpozna metody jako boksu, chyba że znajduje się ona w slots:sekcji definicji klasy. Tak więc, chociaż połączenie będzie nadal działać, metoda nie pojawi się w narzędziach do introspekcji.
Chris

19

Słowa kluczowe, takie jak public, privatesą ignorowane w przypadku gniazd Qt. Wszystkie gniazda są w rzeczywistości publiczne i można je podłączyć


31
Gdy metoda jest wywoływana za pośrednictwem mechanizmu sygnał / szczelina, specyfikatory dostępu są ignorowane. Ale automaty to także „normalne” metody. W przypadku wywołania ich w tradycyjny sposób uwzględniane są specyfikatory dostępu.
Borges

4
@borges i przyszli czytelnicy. W Qt5 metoda connect () może używać wskaźników do funkcji (co ma zalety). Jeśli łączysz się ze wskaźnikami funkcji, specyfikatory dostępu są wymuszane w mechanizmie sygnałów / gniazd.
Tod

3
@borges Uważam, że to nieprawda, a przynajmniej wyjaśnienie było niejasne. Specyfikatory dostępu nie ograniczają możliwości podłączania sygnałów do gniazd; to znaczy do dowolnego sygnału można podłączyć prywatne gniazdo . Specyfikator dostępu chroni jednak funkcję składową przed jej klasą (w typowy sposób) podczas jej wywoływania. Tak więc specyfikatory dostępu nie są „ignorowane”, gdy są wywoływane przez mechanizm sygnału / szczeliny: nie mają one wpływu na łączenie gniazd z sygnałami, ale chronią funkcję przed thisznanym nam sposobem.
To Twoja aplikacja LLC

4

Zadeklarowanie gniazd jako prywatnych oznacza, że ​​nie będziesz w stanie odwoływać się do nich z kontekstu, w którym są prywatne, jak w przypadku każdej innej metody. W konsekwencji nie będziesz mógł przekazywać adresów prywatnych slotów do connect.

Jeśli deklarujesz sygnał jako prywatny, mówisz, że tylko ta klasa może nim zarządzać, ale wskaźniki składowe funkcji nie mają ograniczeń dostępu :

class A{
    private:
    void e(){

    }
    public:
    auto getPointer(){
        return &A::e;   
    }
};

int main()
{
    A a;
    auto P=a.getPointer();
    (a.*P)();
}

Poza tym ważne są również inne odpowiedzi:
- nadal możesz łączyć prywatne sygnały i sloty z zewnątrz za pomocą sztuczek
- signalsi slotssą to puste makra i nie łamią standardu językowego


Dlaczego to pytanie nie ma żadnych głosów za? Czy coś jest z tym nie tak? Uważam, że stwierdzenie, że slotsjest to makro , jest pomocne. Nie mogę podłączyć prywatnych wskaźników funkcji slotów connectbez sztuczek, prawda?
Arch Linux Tux

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.