1

I am trying to rewrite code written in Java to C++, using templates. Here is an example.

Code looks like this:

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

I want to call a updateBook or fireBook in the dispatch() function but, In C++, I think there is no way to know what is in the typename.

Is there a C++ equivalent of Java's getMethod?

Guido Gautier
  • 1,237
  • 9
  • 13
JuHwang Kim
  • 53
  • 1
  • 6

4 Answers4

1

You cannot select a function at run time like in Java. You could use dynamic_cast<> to determine the type of object and then call the proper function.

A better solution in my opinion is to make the two classes share the same function:

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

Then you can call genericBook in your for loop and it takes care of which of those two functions need to be called.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
0

You may try to check against the type using dynamic_cast.
But the same powerful reflection as in Java does not exist in C++, you can see implementation specific.

Anyway, not sure I understand your question correctly.

sergtk
  • 10,714
  • 15
  • 75
  • 130
0

This question is somewhat related to C++ Get name of type in template, the accepted answer should be sufficient, i. e. defining a kind of parser within the code. Altenatively you can use type_info

Community
  • 1
  • 1
Sebastian
  • 8,046
  • 2
  • 34
  • 58
0

If you're using features of the latest standard (C++11, previously known as C++0x), I suggest you go with lambda expressions and generalised function pointer:

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

If you are unable to use C++11 then you can use Boost::function instead, but it will be way less clear.

As a side note, in most cases you should use std::vector instead of std::list.

gwiazdorrr
  • 6,181
  • 2
  • 27
  • 36