C++ 将私有纯虚方法重写为 public

C++ override private pure virtual method as public

为什么会这样?

http://coliru.stacked-crooked.com/a/e1376beff0c157a1

class Base{
private:
    virtual void do_run() = 0;
public:
    void run(){
        do_run();
    }
};

class A : public Base {
public:
    // uplift ??
    virtual void do_run() override {}
};


int main()
{
    A a;
    a.do_run();
}

为什么我可以将 PRIVATE 虚拟方法重写为 public?

这种行为是有意的。如果一个方法是虚拟的,那么它意味着可以通过派生 类 进行自定义,而不管访问修饰符如何。

here

根据https://en.cppreference.com/w/cpp/language/virtual#In_detail 重写基类的virtual 成员函数只关心函数名、参数、const/volatile-ness 和ref 限定符。它不关心 return 类型、访问修饰符或其他您可能希望它关心的事情。

链接参考还特别指出:

Base::vf does not need to be visible (can be declared private, or inherited using private inheritance) to be overridden.

我找不到任何明确允许执行此操作的内容,但覆盖规则不会阻止它。凭借 virtual 函数和覆盖现有函数且不禁止这种情况的函数,它是允许的。

如果您要问为什么语言是这样的,您可能需要问标准化委员会。

Why I can override PRIVATE virtual method as public???

因为你以错误的角度看待基方法是私有的。 B::do_run 私有意味着 "only members and friends of this class can use it"。要禁止派生 classes 覆盖它,我们需要单独的说明符,但我们可以简单地使其不是 virtual。 Class A 另一方面允许任何人调用 A::do_run() 并且由 class A 设计师决定。所以没有像你看到的那样提升。

请注意,此实现不会更改基 class 的访问方式和构造:

Base& b = a;
b.do_run();

将不起作用。

我记得 Scott Meyers 在 "Effective C++" 中更详细地描述了它背后的一些基本原理。但关键的实用功能是能够在相反的方向上使用这种灵活性,在派生的 class 中用私有函数覆盖 public base class 成员,迫使客户端使用 base class 作为接口,不要试图直接使用应该保持隐藏实现的派生接口。

如果打算为base-class编写一个私有代码&以防止覆盖它的可能性,在baseclass中实现私有函数,并声明它final,否则:什么时候应该有人使用私有虚拟机? ISOCPP.ORG FAQ