简体   繁体   中英

Derived class not calling member function of base class

Say I have a class event_base defined like so

template<typename ... Args>
class event_base{
    public:
        using delegate_type = std::function<void(Args...)>;
        using id_type = size_t;

    protected:
        std::vector<std::tuple<delegate_type, id_type>> m_funcs;
};

Then I have some derived classes based on whether an event is mutable and/or callable

mutable:

template<typename ... Args>
class event_mutable: public event_base<Args...>{
    public:
        using id_type = typename event_base<Args...>::id_type;

        template<FunctorType>
        id_type connect(FunctorType &&f){
            this->m_funcs.emplace_back(f, ++m_last_id);
            return m_last_id;
        }

        bool disconnect(id_type id){
            for(auto iter = begin(this->m_funcs); iter != end(this->m_funcs); ++iter)
                if(std::get<1>(*iter) == id){
                    this->m_funcs.erase(iter);
                    return true;
                }
            return false;
        }
};

callable:

template<typename ... Args>
class event_callable: public event_base<Args...>{
    public:
        void operator()(Args ... args) const{
            for(auto iter = this->m_funcs.rbegin(); iter != this->m_funcs.rend(); ++iter)
                (std::get<0>(*this))(args...);
        }
};

and for both:

template<typename ... Args>
class event: public event_mutable<Args...>, public event_callable<Args...>{};

Casting between the types and such works fine, but for some reason when I call an event like this ...

event<int> int_ev;
int_ev.connect(/* ... some function ... */);
int_ev(5);

... the connected function isn't called!

This leads me to believe that the operator() defined in event_callable isn't being called correctly or the vector m_funcs isn't being traversed within the method.

What am I doing wrong here and/or why isn't the vector being iterated over?

You have a diamond-shaped inheritance, which means that in your situation, event gets two versions of m_funcs ; one coming from event_mutable , and one from event_callable . Therefore, connect() populates event_mutable::m_funcs , and operator() searches in event_callable::m_funcs . You should use virtual inheritance to overcome this problem:

class event_callable: public virtual event_base { ... };
class event_mutable: public virtual event_base { ... };

class event: public event_callable, public event_mutable { ... };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM