在基类中存储指向派生类函数的指针
Posted
技术标签:
【中文标题】在基类中存储指向派生类函数的指针【英文标题】:Store Pointer to Derived Class Function in Base Class [duplicate] 【发布时间】:2018-10-11 21:32:42 【问题描述】:我想创建一个方法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
中定义函数?
【问题讨论】:
Why can't I cast a pointer to Derived class member function to the same but of class Base?的可能重复 【参考方案1】:您无法将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
,而不是函数指针。
【讨论】:
这看起来很有希望——但是,在 schedule_function 的实现(.cpp 文件)中,它不允许我将参数更改为void (T::*func)()
。在标题声明中使用void (T::*func)()
时,我是否使用void (Strategy::*func)()
保持相同的方式?
@EvanKirkiles 如果您想在多个翻译单元中使用模板,您需要将函数定义放入标题中。【参考方案2】:
不能将派生类函数指针存储在基类函数指针中。
另一种方法是使用 Strategy*
参数存储函数:
class Strategy
...
void schedule_function(function<void(Strategy*)> func)
heap_eventlist.emplace_back(std::make_unique<ScheduledEvent>(func));
;
然后您可以直接使用 Strategy 的成员函数:
BasicAlgo g;
g.schedule_function (&BasicAlgo::f); // f is a member function of Strategy
但您也可以提供任何其他接受策略指针作为参数的函数。如果您的 Strategy 是一个多态类,那么您可以尝试安全地向下转换 Strategy
指针并调用派生类的成员函数。
g.schedule_function ([](Strategy *x)->void
BasicAlgo*b=dynamic_cast<BasicAlgo*>(x);
if (b) b->ff();
);
这里是demo。
【讨论】:
+1 也是很好的解决方案!但是,我试图让 schedule_function 易于为其他人实现,并且这些 lambdas 使用起来比 user207 的答案更复杂。以上是关于在基类中存储指向派生类函数的指针的主要内容,如果未能解决你的问题,请参考以下文章
使用基类中定义的函数返回指向派生类实例的指针时出现无效转换错误