关于oop:C ++将私有纯虚方法覆盖为public

C++ override private pure virtual method as public

为什么会这样?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();
}

为什么我可以将私有虚拟方法重写为公共方法?


根据https://en.cppreference.com/w/cpp/language/virtual中的详细介绍,重写基的virtual成员函数只关心函数名、参数、const/volatile和ref限定符。它不关心返回类型、访问修饰符或其他您可能期望它关心的事情。

链接的引用还特别注意到:

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

我找不到任何明确允许这样做的东西,但是覆盖规则并不能阻止它。它可以通过virtual函数和函数来覆盖现有的,而不是不允许这种情况发生。

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


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

请看这里


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

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

不起作用。

我记得Scott Meyers在"有效C++"中更详细地描述了它背后的一些原理。但是,关键的实际特性是能够在相反的方向上使用这种灵活性,在派生类中使用私有函数覆盖公共基类成员,从而强制客户机使用基类作为接口,而不希望直接使用应保持隐藏实现的派生类。


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

因为您看到基方法在错误的角度上是私有的。B::do_run是私有的,意思是"只有这个阶级的成员和朋友才能使用它"。为了禁止派生类重写它,我们需要单独的说明符,但我们可以简单地使它不是virtual。另一方面,类A允许任何人打电话给A::do_run(),由类A设计师决定。所以你看不到隆起。


如果目的是为基类编写私有代码,以防止重写它的可能性,请在基类中实现私有函数,并声明它final,否则:什么时候应该使用私有虚拟机?isocpp.org常见问题解答