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()//我已经注意到这种情况好几次了,并且没有找到与require
public
最终实现不同的解决方案。尽管可以对方法进行
private
主基声明,但前提是您有多个继承级别。@πάνταῥεῖ: 它只是比它应该的更迂回:
template void callBase(T*p){(p->*FP)(;}
,用
callBase调用(this)。可能是可优化的,这样就不会有任何理由让你公开继承和回调保护了。在我看来这是显而易见的选择。“亚历克斯,实际上这是最好的解决方案,实际上它也适用于我原来的问题,不知道为什么我没有考虑这个问题。”亚历克斯:你应该。一定要把它作为一个答案。