Сохранить указатель на производную функцию класса в базовом классе

Я хочу создать метод schedule_function который сохраняет указатель на функцию-член объекта BasicAlgo в ScheduledEvent , но не имеет указанной функции, определенной в родительском классе BasicAlgo , Strategy . Прямо сейчас я использую этот метод, который прекрасно работает для сохранения функций в Strategy но не будет работать для функций BasicAlgo :

class Strategy {

schedule_function(void (Strategy::*func)()) {
    // Puts the scheduled event built with the strategy function onto a list
    heap_eventlist.emplace_back(std::make_unique<events::ScheduledEvent>(func));
}}

Я попытался заменить Strategy::*func на Strategy*::*func но это привело к ошибкам компилятора, и это не кажется правильным.

Есть ли способ получить указатель на функцию-член из производного класса BaseAlgo в качестве параметра в базовом классе Strategy без определения функции в Strategy ?

Всего 2 ответа


Невозможно сохранить функцию-член функции BaseAlgo в указателе на функцию-член Strategy .

Вы можете сохранить функцию-член BaseAlgo в указателе на функцию-член BaseAlgo , и вы можете использовать такой тип указателя с CRTP:

template<class T>
struct Strategy {
    void schedule_function(void (T::*func)());
};

struct BasicAlgo : Strategy<BasicAlgo> {
    void memfun();
};

int main() {
    BasicAlgo b;
    b.schedule_function(&BasicAlgo::memfun);
}

В противном случае вы можете использовать оболочку функции стирания типа, такую ​​как std::function вместо указателя функции.


Невозможно сохранить указатель функции производного класса в указателе функции базового класса.

Альтернативой является сохранение функции с аргументом Strategy* :

class Strategy {
    ...
    void schedule_function(function<void(Strategy*)> func) {
        heap_eventlist.emplace_back(std::make_unique<ScheduledEvent>(func));
    }
}; 

Затем вы можете просто использовать функцию-член Стратегии:

BasicAlgo g;
g.schedule_function (&BasicAlgo::f);   // f is a member function of Strategy

Но вы также можете предоставить любую другую функцию, которая принимает указатель стратегии как аргумент. Если ваша Стратегия является полиморфным классом, вы можете попытаться безопасно понизить указатель Strategy и вызвать функцию-член производного класса.

g.schedule_function ([](Strategy *x)->void {
                       BasicAlgo*b=dynamic_cast<BasicAlgo*>(x); 
                       if (b) b->ff(); 
                    });

Вот демо .


Есть идеи?

10000