2016-11-02 6 views
4

私はcode I foundを変更しようとしているが、私は私の目的の理解の欠如、重要性、および/またはこの仮想オペレータの関連性によってブロックされています:誰かが、なぜこのオペレータに洞察を提供することができここで仮想演算子()()の目的は何ですか?

    1. 必要か有用か?
    2. パラメータとしてparentItem(),rect_、およびresizer_が必要と思ったら、resizer_の値を変更しますか?

    コンストラクタ.Hで:の.cppで

    virtual void operator()(QGraphicsItem* item, const QRectF& rect) = 0;

    コール:

    (*resizer_)(parentItem(), rect_);

    参照のコンストラクタのためのトリミングコンテキスト:

    class SizeGripItem : public QGraphicsItem 
    { 
        private: 
    
         class HandleItem : public QGraphicsRectItem 
         { 
          public: 
           HandleItem(int positionFlags, SizeGripItem* parent); 
    
          private:  
           SizeGripItem* parent_; 
         }; 
    
        public: 
         class Resizer 
         { 
          public: 
           virtual void operator()(QGraphicsItem* item, 
                 const QRectF& rect) = 0; 
         }; 
    
         SizeGripItem(Resizer* resizer = 0, QGraphicsItem* parent = 0); 
         virtual ~SizeGripItem(); 
    
        private: 
         void doResize(); 
         QRectF rect_; 
         Resizer* resizer_; 
    }; 
    
  • +0

    はfunctionオブジェクトのようです。 – Naidu

    +0

    'Resizer'は、' sizeGripItem'のクライアントが( 'doResize()'を呼び出す) 'set_x_'メンバ関数のどれかが' rect_'メンバにアクセスできるようにコールバックを持つ方法ですと呼ばれる。 – quamrana

    答えて

    3

    点2については、次の行を考える:

    (*resizer_)(parentItem(), rect_); 
    

    resizer_は、おそらく未知のタイプTのオブジェクトへのポインタであり、こうして*resizerは、同じタイプTのオブジェクトへの参照です。
    タイプが2つのパラメータ(たとえば、decltype(parentItem())およびdecltype(rect_))を受け入れる定義がoperator()の場合、この例のように呼び出すことができます。それがすべてでresizer_の値を変更しません

    resizer_->operator()(parentItem(), rect_); 
    

    :他の点で
    は、それはと同等です。

    この演算子が必要または有用である理由について、誰かが洞察を提供することはできますか?

    よく、それは解決することを目指す実際の問題と文脈に大きく左右されます。
    コード行からは言い難いです。
    無駄な場合は、使用しないでください。それで全部です。

    +0

    はい。私は2つのものを欠いている。 1つは、純粋な仮想として宣言されているため、使用前にオーバーライドされたバージョンが必要な場合もあります。これらの関数オブジェクト型の多くは、(STL関数で使用されているように)主に述語として使用されますが、ここでは通常の関数として使用されます。 – Naidu

    +0

    @PAVANCHANDAKA純粋な仮想メソッドは、言語の機能です。私はそれが適切な定義を与えることができなかったと思うし、ライブラリのデザイナーは、ユーザーがそれを定義させるように選択しました。他の質問は疑問です、通常の関数は述語として使用することができるので、問題はありません。 – skypjack

    +0

    お返事ありがとうございます。 – Naidu

    4

    Resizerは、polymorphic functor(機能オブジェクト)での試みであるbrokenです。このようなイディオムは、C++ 11より前には便利でした。そのようなファンクタは仮想デストラクタなしでは役に立たないので、壊れています。次のように見ているべきである:

    class Resizer { 
    public: 
        virtual void operator()(QGraphicsItem* item, const QRectF& rect) = 0; 
        virtual ~Resizer() {} 
    }; 
    

    このようなオブジェクトは、呼び出し可能である:

    void invokeResizer(Resizer * resizer, QGraphicsItem * item, const QRectF & rect) { 
        (*resizer)(item, rect); 
    } 
    
    resizer

    上記オブジェクトのメソッドoperator()(QGraphicsItem*,const QRectF&)を実行します。

    最新のコードでは、このようなハッキングの代わりに、std::function<void(QGraphicsItem*, const QRectF &)>を使用する必要があります。

    +0

    技術的に、破壊するものがなければ、仮想デストラクタを持たないことは安全です。 – dtech

    +3

    @ddriverそのクラスはポリモーフィックで抽象的です。オーバーロードされることを意味します。仮想デストラクタが存在しないということは、このような各クラスのエラーです。ファンクタが状態を保持できない場合は、(ファンクションポインタの代わりに)ファンクタを使用する必要はありません。ファンクタは状態を保持することができます(理由はオブジェクトです)、仮想デストラクタが必要です。それについては何もしない。 C++では、ファンクタは状態を保持できる呼び出し可能ファイルのイディオムです。ステートレスな呼び出し可能関数を使用するには、関数ポインタを使用します。これは、「状態が許可されていない」ことを明確に示すイディオムです。 –

    +0

    これは理論的には未定義の動作ですが、実際には何が起こるのかは、型ポインタのデストラクタが呼び出されていることです。これは、基本クラスのデストラクタになります。派生メンバーが余分なメンバーを追加せず、単に機能をオーバーライドすると、メンバーは破棄されません。メモリを解放することも問題ではありません。フラグメントのサイズは、通常、フラグメント自体に最初に格納されるためです。オーバーロードは必ずしもメンバーの追加を意味するものではありません。機能をオーバーライドしたり、機能を追加したりすることができます。どちらの場合でも、派生したデストラクタの代わりにベースを実行すると、実質的に問題ありません。 – dtech

    関連する問題