Qt「プライベートスロット:」これは何ですか?


82

使い方はわかりますが、構文が気になります。「プライベートスロット」とは何ですか?

クラス定義でprivateキーワードと:の間に何かを見たことがありません。ここで起こっている素晴らしいC ++の魔法はありますか?

そしてここの例:

 #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
これは標準のC ++ではありません。これはQTフレームワーク構造です。QT信号とスロットを検索します
Alok Save 2012

1
C ++としてコンパイルする場合は、としてslots定義され#define slotsます。Qt MOCを使用してコンパイルすると、C ++コンパイラのコードが生成されます。
dalle 2012

2
笑私は長い間C ++を使用していなかったので、これを理解するのはさらに困難でした。彼らは何か新しいものを追加したと思いました
dtc 2015年

回答:


56

スロットは、C ++のQt固有の拡張機能です。Qtのプリプロセッサであるメタオブジェクトコンパイラ(moc)を介してコードを送信した後にのみコンパイルされます。ドキュメントについては、http://doc.qt.io/qt-5/moc.htmlを参照してください。

編集:フランクが指摘するように、mocはリンクにのみ必要です。余分なキーワードは、標準のプリプロセッサで#definedされます。


おかげで、Qtのプリプロセッサは、何が起こっているのかという私のメンタルモデルに欠けていたものです。
ジャスティン

16
正しくありません。「シグナル」と「スロット」は空の定義であるため、コードは常にコンパイルされるため、コンパイラーはそれらを認識しません。これらのマクロは、追加のコードを生成するmocのヒントです。元の.hファイルと.cppファイルは変更されず、mocがなくても問題なくコンパイルされます。mocで生成された定義(シグナル定義、メタオブジェクトなど)が他の方法で欠落しているため、失敗するのはリンクです。
フランクオスターフェルト2012

1
あるslotsキーワードが必要?slotsキーワードなしでスロットを呼び出すいくつかの小さなQtプログラムをコンパイル/リンクしようとしましたが、それらはうまく構築されました。私の実験では、次のことsignals:が示されています。他の場所で読んだようにslots、間違いなく必要であり、不要である可能性があり、不要のemitようです。
It's Your App LLC 2014

1
slotsQt5では必要ありません。Qtはconnect()構文を更新して、ラムダを含む任意の関数にシグナルを接続できるようにしました。このため、slots必要ありません。ただし、slotsキーワードはオブジェクトの作成方法に影響しますQMetaObjectmoc(別名「メタオブジェクトコンパイラ」)はslots:、クラス定義のセクション内にない限り、メソッドをスロットとして認識しません。そのため、接続は引き続き機能しますが、メソッドはイントロスペクションツールに表示されません。
クリス

19

、などのキーワードはQtスロットpublicprivateは無視されます。すべてのスロットは実際にはパブリックであり、接続できます


30
メソッドがシグナル/スロットメカニズムを介して呼び出される場合、アクセス指定子は無視されます。しかし、スロットも「通常の」方法です。従来の方法を使用してそれらを呼び出す場合、アクセス指定子が考慮されます。
ボルヘス2012

4
@borgesと将来の読者。Qt5では、connect()メソッドは関数ポインターを使用できます(これには利点があります)。関数ポインタを使用して接続する場合、アクセス指定子はシグナル/スロットメカニズムで適用されます。
トッド

3
@borgesこれは間違っているか、少なくとも説明が不明確だったと思います。アクセス指定子は、信号をスロットに接続する機能を制限しません。つまり、プライベートスロットは任意の信号に接続できます。ただし、アクセス指定子は、呼び出されている間、メンバー関数をそのクラスから(通常の方法で)保護します。したがって、アクセス指定子は、シグナル/スロットメカニズムを介して呼び出されたときに「無視」されません。スロットをシグナルに接続することには関係ありませんthisが、使い慣れた方法で関数を保護します。
It's Your App LLC 2014

4

スロットをプライベートとして宣言することは、他の方法のように、スロットがプライベートであるコンテキストからスロットを参照できないことを意味します。したがって、プライベートスロットアドレスをに渡すことはできませんconnect

シグナルをプライベートとして宣言すると、このクラスのみがシグナルを管理できるが、関数メンバーポインターにはアクセス制限がないということになります

class A{
    private:
    void e(){

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

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

それ以外に、他の回答が述べていることも有効です:
-トリックで外部からプライベート信号とスロットを接続することができます
-signalsそしてslots空のマクロであり、言語標準を破ることはありません


この質問に賛成票がないのはなぜですか?何か問題がありますか?私はその声明を見つけました、それslotsはマクロが役に立ちます。connectトリックなしでプライベートslot-function-pointersを接続することはできませんか?
Arch Linux Tux 2018

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.