我遇到了可以访问方法的应用程序:
void AttachCallback(int event, std::functional<void(int)> cb);
允许我将回调cb
附加到事件event
。我还有几个类需要将回调附加到其构造函数中的几个事件,并为它们绑定的每个事件实现回调。因此,首先想到的实现看起来像:
class MyClass {
public:
MyClass() {
AttachCallback(0, [this](int value) { cb0(value); });
AttachCallback(2, [this](int value) { cb2(value); });
// ... as necessary
}
private:
void cb0(int value) { /*... callback for event 0 ...*/ }
void cb2(int value) { /*... callback for event 2 ...*/ }
// ... as necessary
};
但是,由于我最近一直在使用模板,我想知道是否可以创建一个模板化的纯虚拟类来监听给定事件并按如下方式使用它:
template<const int EVENT>
class ListensToEvent {
public:
virtual ~ListensToEvent() = default;
protected:
ListensToEvent() {
AttachCallback(EVENT, [this](int value) { cb(value); });
}
virtual void cb(int value) = 0;
};
class MyClass : public ListensToEvent<0>, public ListensToEvent<2> {
private:
void cb(int value) override;
};
template<> // This line makes me suspicious
void MyClass::ListensToEvent<0>::cb(int value) {
/*... callback for event 0 ...*/
}
template<>
void MyClass::ListensToEvent<2>::cb(int value) {
/*... callback for event 2 ...*/
}
在搜索相关主题时,我发现this thread显示了如何使用辅助类来修复当两个基本接口提供相同标识符纯虚方法时发生的冲突。因为我在这里使用模板,所以我无法使用这样的帮助器,因为我不知道可能有多少个实例,但我发现声明方法没有专门化,然后在类定义之外提供模板特化允许我单独定位每个基类的方法(如上所示)。
在测试时,我构建了这种设计的简化(没有回调),只是为了表明它编译并专门化here。
首先,我关心的是我对其原理的理解。通过使用cb
或cb
限定ListensToEvent<0>
,我可以在课程定义后指定我正在实施哪个ListensToEvent<2>
,这是有道理的。我不明白的是,为什么该资格认定为模板专业化,因此需要行template<>
。另外,如果这些资格实际上是模板特化,那么C ++究竟如何查看方法特化以及它们为什么有效?
话虽如此,我也对有关此设计功能的评论感兴趣。它是一种简化MyClass的有效方法,也是其他兄弟姐妹的实现,还是我提出的第一种方式更好?或者还有另一种设计在这种情况下效果最好吗?