C++ 在子类中重写时如何调用私有虚拟基类实现
我有这样的类层次结构:C++ 在子类中重写时如何调用私有虚拟基类实现,c++,inheritance,virtual,C++,Inheritance,Virtual,我有这样的类层次结构: class Base { public: void start() { init(); } private: virtual void init() = 0; }; class Default : public Base { private: virtual void init() override {/*default implementation*/}; }; class Special : public Default { private: vi
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/};
};
class Special : public Default
{
private:
virtual void init() override final {/*specialized implementation*/};
}
如果我在一个特殊类型的对象上调用start,它就可以正常工作
现在我有一个例子,在特殊类的实现中,我想调用默认类的实现。
通常情况下,这将适用于Default::init;,但是由于默认声明这是私有的,所以将在这里失败
显然,一个解决方案是将其从私有更改为受保护,但我想问是否还有其他方法?我不允许任何子级直接调用此函数,而是将其限制为通过已在基类或默认类中定义的虚拟函数启动的调用
是否有一些选项或修饰符允许成员函数调用仅在子类位于同一重写虚拟成员函数中时才允许从子类调用?C++没有提供直接实现这一点的方法,因此您必须解决这个问题,例如。G在下面的一段代码中 好吧,如果你真的想的话。我个人宁愿退回到保护函数,记录它们的用途和调用时间,然后信任派生类正确地完成这些工作。这最终保持了接口的干净性,并且不依赖于一个非常不寻常的,也许是丑陋的模式,实际上它会传递两次 如果要将此约束应用于多个函数,可以让代理接受成员函数指针,这样就不必分别为每个函数重新编写代理。如果函数参数不同,您可能需要在此基础上创建一个模板。Forward declare Special,并使其成为默认的朋友:
我想不,这是不可能的。这正是protected的用法,允许从一个具有公共继承权的子级访问。我唯一能想到的是让派生类成为好友。@在这种情况下,我认为好友比protected更邪恶;它将允许访问可能更多的内容,并且需要修改基类,每个新的派生类都需要类似的访问权限……然而friend是邪恶的。
class Base
{
public:
virtual ~Base() { }
void start()
{
InitProxy p(*this);
init(p);
}
protected:
class InitProxy
{
public:
InitProxy(InitProxy const&) = delete;
void init()
{
m_base.Base::init(*this);
}
private:
friend class Base;
Base& m_base;
InitProxy(Base& base)
: m_base(base)
{ }
};
private:
virtual void init(InitProxy& proxy) { }
};
class Derived : public Base
{
void init(InitProxy& proxy) override
{
proxy.init();
}
};
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Special; // Forward declaration
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/}
friend class Special; // Friend declaration
};
class Special : public Default
{
private:
virtual void init() override final {
Default::init();
/*Other implementation*/
}
};