0

スニペットを検討してください:

# include <iostream>

# include <boost/scoped_ptr.hpp>
# include <boost/shared_ptr.hpp>

# include <boost/function.hpp>
# include <boost/array.hpp>
# include <boost/asio.hpp>
# include <boost/thread.hpp>
# include <boost/thread/locks.hpp>
# include <boost/bind.hpp>
# include <boost/noncopyable.hpp>

# include <boost/variant.hpp>


class DataLink {};
class Metadata {};
class Image {};

 typedef boost::function<void( DataLink const&, Metadata const& , Image const& )> Handler ; 
 typedef boost::function<void( Metadata const& , Image const& )> Handler2 ; 
 typedef boost::function<void( Image const& )> Handler3 ; 

typedef boost::variant<DataLink, Metadata, Image> Variant; 



enum callbackHandler { link_enum, meta_enum, image_enum };
class Worker {
  Handler  callBack ;
  //Handler2 callBack2 ;
  //Handler3 callBack3 ;

  DataLink dlink;
  Metadata meta ;
  Image    img ;

  callbackHandler handlerEnum ;

public :
  Worker ( const Handler& handler ) 
  : callBack ( handler ) 
   {}
  //Worker ( const Handler2& handler ) 
  //: callBack2 ( handler ) 
  // {}
  //Worker ( const Handler3& handler ) 
  //: callBack3 ( handler ) 
  // {}

  void Image ( ) {
    // update the img object 
    // invoke call back 
    handlerEnum = image_enum ;
    //const std::type_info& xxx = callBack.target_type();
    //std::cout << xxx.raw_name() << std::endl;
    callBack ( dlink, meta, img ) ;
  }

  void Metadata ( ) {
    // update the meta object 
    // invoke call back 
    handlerEnum = meta_enum ;
    callBack ( dlink, meta, img ) ;
  }

  void Dlink ( ) {
    // update the link object 
    // invoke call back 
    handlerEnum = link_enum ;
    callBack ( dlink, meta, img ) ;
  }

  callbackHandler getHandlerType() { return handlerEnum ; }
};

class Foo {
  Worker *ptrWorker ;
public :
  Foo () 
  : ptrWorker( 0 ) 
  {}

  void callback ( DataLink const& d, Metadata const& m , Image const&  i ) {
    callbackHandler tt = ptrWorker->getHandlerType();
    if ( tt == image_enum ) {
      std::cout <<  "Image object " << std::endl;
    }
    if ( tt == meta_enum ) {
      std::cout <<  "Meta object " << std::endl;
    }
    if ( tt == link_enum ) {
      std::cout <<  "Link object " << std::endl;
    }

  }
  bool start () {
    ptrWorker = new ( std::nothrow ) Worker ( boost::bind ( &Foo::callback, this, _1, _2, _3 ) );
    if ( !ptrWorker ) {
      return - 1 ;
    }
  }
  void testWorker() {
    ptrWorker->Image() ;
    ptrWorker->Metadata() ;
    ptrWorker->Dlink() ;
  }
};

int main() {
  Foo f;
  f.start() ;
  f.testWorker() ;
  std::cin.get() ;
}

コンストラクターをコメントアウトすると、Handler2 と Handler3 のサポートを追加できますが、Worker クラスのコンストラクターに渡されたハンドラーを特定する方法はありますか? 現在、メンバ関数 Metadata、Image、Dlink は「callBack」オブジェクトを使用しています。ユーザーハンドラーが別のハンドラーを渡した場合は、区別する必要があります-たとえば、Handler2

実装するために列挙型を使用する必要があるという事実は、実質的に私自身の型システム (差別的な共用体の行 - 別名、バリアント) であり、設計を少し再考する必要があることの確かな兆候でもあります。その場合、私は再設計のために開いています。クラスで定義された N-1 個のダミー ハンドラー (つまり、一度に 1 つのハンドラーのみが使用され、他のハンドラーは何もしない) を持たなければならないことは、オブジェクト モデルが混乱し、凝集度が低くなりますが、誰にもわかりません。

4

1 に答える 1

0

仮想基本クラスから派生したファンクターを使用してこれを実装できます。

struct CallbackBase
{
    // Dummy virtual functions that does nothing
    virtual operator()(DataLink const &, Metadata const &, Image const &) {}
    virtual operator()(Metadata const &, Image const &) {}
    virtual operator()(Image const &) {}
};

class Worker
{
    CallbackBase &callback_;

public:
    Worker(const CallbackBase &callback)
        : callback_(callback)
        { }

    void Image()
        {
            // Do something...

            callback_(img);
        }

    void Metadata()
        {
            // Do something...

            callback_(meta, img);
        }

    void Dlink()
        {
            // Do something...

            callback_(dlink, meta, img);
        }
};

struct MyCallback : public CallbackBase
{
    virtual operator()(Image const &)
        {
            // Do something useful here
        }
};

MyCallback my_callback;
Worker my_worker(my_callback);

基本コールバック クラスのオーバーロードによりWorker、派生コールバック クラスで実際に必要なコールバックのみを実装しながら、クラスは適切な場所でそれらのいずれかを呼び出すことができます。

于 2012-08-28T06:16:31.687 に答える