为什么会这样?
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 虚拟方法覆盖为公共?
答案 0 :(得分:16)
根据https://en.cppreference.com/w/cpp/language/virtual#In_detail覆盖基类的virtual
成员函数,只关心函数名,参数,const / volatile-ness和ref限定符。它不关心返回类型,访问修饰符或您可能期望它关心的其他事情。
链接引用还特别指出:
Base :: vf不需要是可见的(可以声明为私有,或使用私有继承继承)来覆盖。
我无法明确找到的任何内容都允许这样做,但是覆盖规则并不能阻止它。凭借virtual
函数和函数覆盖现有而不允许这种情况允许它。
如果你问为什么这就是语言的方式,你可能不得不问标准化委员会。
答案 1 :(得分:11)
这种行为是有意的。如果某个方法是虚拟的,则无论访问修饰符如何,它都可以通过派生类进行自定义。
请参阅here
答案 2 :(得分:2)
为什么我可以将PRIVATE虚方法覆盖为public ???
因为你看错了角度的私有基本方法。私有的B::do_run
意味着“只有这个类的成员和朋友才能使用它”。要禁止派生类覆盖它,我们需要单独的说明符,但我们可以简单地使它不是virtual
。另一方的班级A
允许任何人拨打A::do_run()
并由班级A
设计师决定如此。所以你看到它没有隆起。
答案 3 :(得分:2)
请注意,此实现不会更改基类的访问方式和构造:
Base& b = a;
b.do_run();
不起作用。
我记得在#34; Effective C ++"中有更详细的描述背后有一些基本原理。作者:Scott Meyers。但关键的实际特性是能够在相反的方向上使用这种灵活性,在派生类中使用私有函数覆盖公共基类成员,迫使客户端使用基类作为接口,而不是试图直接使用派生的应该仍然是一个隐藏的实现。
答案 4 :(得分:0)
如果要为基类编写私有代码并防止覆盖它,请在基类中实现私有函数,并声明为final
,否则:何时应使用私人虚拟机? ISOCPP.ORG FAQ