C++ 来自专用CRTP基地的回调
下面的代码不起作用,因为您不能从私有基类C++ 来自专用CRTP基地的回调,c++,C++,下面的代码不起作用,因为您不能从私有基类static\u cast 用C风格的cast替换cast是可行的(虽然我最初认为这会调用未定义的行为,显然它不会,请参见),但这相当难看,因为它还允许您绕过常量检查等。另一种方法是让CRTPBase成为朋友,但这会暴露派生的所有私有成员 有没有另外一种不用C风格的演员阵容和不让CRTPBase成为朋友的写作方法 template<typename T> struct CRTPBase { void callBase() {
static\u cast
用C风格的cast替换cast是可行的(虽然我最初认为这会调用未定义的行为,显然它不会,请参见),但这相当难看,因为它还允许您绕过常量检查等。另一种方法是让CRTPBase成为朋友,但这会暴露派生的所有私有成员
有没有另外一种不用C风格的演员阵容和不让CRTPBase成为朋友的写作方法
template<typename T>
struct CRTPBase {
void callBase() {
T * derived = static_cast<T*>(this);
derived->publicMethod();
}
};
struct Derived : private CRTPBase<Derived> {
void callParent() { this->callBase(); }
void publicMethod() {}
};
int main() {
Derived d;
d.callParent();
return 0;
}
模板
结构CRTPBase{
void callBase(){
T*派生=静态_转换(本);
派生->公共方法();
}
};
派生结构:私有CRTPBase{
void callParent(){this->callBase();}
void publicMethod(){}
};
int main(){
导出d;
d、 callParent();
返回0;
}
这不是一个理想的解决方案,但您可以将友谊限制为一种独特的方式,如下所示:
template<typename T>
struct CRTPBase {
friend T; // So T can see asDerived.
void callBase() { asDerived()->publicMethod(); }
private:
T* asDerived() { return static_cast<T*>(this); }
};
struct Derived : private CRTPBase<Derived> {
friend Derived* CRTPBase<Derived>::asDerived();
void callParent() { this->callBase(); }
void publicMethod() {}
};
模板
结构CRTPBase{
friend T;//因此T可以看到派生的。
void callBase(){asDerived()->publicMethod();}
私人:
T*asDerived(){return static_cast(this);}
};
派生结构:私有CRTPBase{
friend-Derived*CRTPBase::asDerived();
void callParent(){this->callBase();}
void publicMethod(){}
};
我认为最好的解决方案是避免私有继承,而是选择数据隐藏。
将成员函数标记为protected将阻止除派生类之外的任何地方的访问。取而代之的是一个额外的公共继承奖金
template<typename T>
class CRTPBase {
protected:
void callBase() {
T * derived = static_cast<T*>(this);
derived->publicMethod();
}
};
struct Derived : public CRTPBase<Derived> {
void callParent() { this->callBase(); }
void publicMethod() {}
};
int main() {
Derived d;
d.callParent();
d.callBase() // <- illegal
return 0;
}
模板
类CRTPBase{
受保护的:
void callBase(){
T*派生=静态_转换(本);
派生->公共方法();
}
};
派生结构:公共CRTPBase{
void callParent(){this->callBase();}
void publicMethod(){}
};
int main(){
导出d;
d、 callParent();
d、 callBase()//我已经注意到这种情况好几次了,并且没有找到与requirepublic
最终实现不同的解决方案。尽管可以对方法进行private
主基声明,但前提是您有多个继承级别。@πάνταῥεῖ: 它只是比它应该的更迂回:template void callBase(T*p){(p->*FP)(;}
,用callBase调用(this)。可能是可优化的,这样就不会有任何理由让你公开继承和回调保护了。在我看来这是显而易见的选择。“亚历克斯,实际上这是最好的解决方案,实际上它也适用于我原来的问题,不知道为什么我没有考虑这个问题。”亚历克斯:你应该。一定要把它作为一个答案。