1

テンプレートを使用して、Javaで記述されたコードをC++に書き直そうとしています。これが例です。

コードは次のようになります。

class IBookUpdatedHandler {
public:
    virtual ~IBookUpdatedHandler() {}
    virtual void updateBook(int bookIndex)=0;
};

class IBookFiredHandler {
public:
    virtual ~IBookUpdatedHandler() {}
    virtual void fireBook(int bookIndex)=0;
};


template <typename T>
class Dispatcher {
private:
    list<T> listeners;
    const char* methodName;

public:
    Dispatcher(const char* name) {
        this->methodName = name;
    }

    void add(T listener) {
        listeners.push_back(listener);
    }

    void dispatch() {
        // listeners loop
        for(typename list<T>::iterator pos = listeners.begin(); pos != listeners.end(); pos++)
        {
            // i don't know what is in the box .. (list<T>)..
            // call ..
            // listener could have (*pos)->do_somethig() ?
        }
    }
};

Dispatcher<IBookUpdatedHandler*> *dispatcher = new Dispatcher<IBookUpdatedHandler*>("updateBook");
Dispatcher<IBookFiredHandler*> *dispatcher = new Dispatcher<IBookFiredHandler*>("fireBook");

関数内でupdateBookまたはを呼び出したいのですが、C ++では、型名に何が含まれているかを知る方法がないと思います。fireBookdispatch()

Javaと同等のC++はありgetMethodますか?

4

4 に答える 4

1

Java のように実行時に関数を選択することはできません。を使用dynamic_cast<>してオブジェクトのタイプを判別し、適切な関数を呼び出すことができます。

私の意見では、より良い解決策は、2 つのクラスが同じ機能を共有することです。

class IBookGenericHandler {
public:
    virtual void genericBook(int bookIndex)=0;
};

class IBookUpdatedHandler:public IBookGenericHandler {
public:
    virtual ~IBookUpdatedHandler() {}
    virtual void updateBook(int bookIndex)=0;
    virtual void genericBook(int bookIndex) { updateBook(bookIndex) }
};

class IBookFiredHandler:public IBookGenericHandler {
public:
    virtual ~IBookUpdatedHandler() {}
    virtual void fireBook(int bookIndex)=0;
    virtual void genericBook(int bookIndex) { fireBook(bookIndex) }
};

genericBook次に、forループで呼び出すことができ、これら 2 つの関数のどちらを呼び出す必要があるかを処理します。

于 2012-04-20T10:06:37.447 に答える
0

dynamic_castを使用して型をチェックしてみてください。
しかし、Java のような強力なリフレクションは C++ には存在せず、実装固有であることがわかります。

とにかく、あなたの質問を正しく理解しているかどうかはわかりません。

于 2012-04-20T10:03:37.623 に答える
0

最新の標準 (C++11、以前は C++0x として知られていた) の機能を使用している場合は、ラムダ式と一般化された関数ポインターを使用することをお勧めします。

template <typename T> 
class Dispatcher { 
private: 
    std::list<T> listeners; 
    std::function<void(T)> caller;

public: 
    Dispatcher(function<void(T)> caller) : caller(caller) {} 

    void add(T listener) { 
        listeners.push_back(listener); 
    } 

    void dispatch() { 
        // listeners loop 
        for(typename std::list<T>::iterator pos = listeners.begin(); pos != listeners.end(); pos++) 
        {
            caller(*pos);
        }
    } 
}; 

Dispatcher<IBookUpdatedHandler*> *dispatcher1 = new Dispatcher<IBookUpdatedHandler*>( 
    [](IBookUpdatedHandler* p) { p->updateBook(0); } 
); 

Dispatcher<IBookFiredHandler*> *dispatcher2 = new Dispatcher<IBookFiredHandler*>( 
    [](IBookFiredHandler* p) { p->fireBook(0); } 
); 

C++11 を使用できない場合は、代わりにBoost::functionを使用できますが、あまり明確ではありません。

補足として、ほとんどの場合、std::vector代わりに を使用する必要がありstd::listます。

于 2012-04-20T10:18:32.583 に答える
0

この質問はC++ Get name of type in templateに多少関連しています。受け入れられた答えで十分です。つまり、コード内で一種のパーサーを定義します。または、使用できますtype_info

于 2012-04-20T10:04:36.927 に答える