如果私有虚函数在派生 class 中被重写为 public 函数,会出现什么问题?

If a private virtual function is overridden as a public function in the derived class, what are the problems?

using namespace std;
#include <cstdio>
#include <iostream>

class One{
    private:
        virtual void func(){
            cout<<"bark!"<<endl;
        }
};

class Two: public One{
    public:
        void func(){
            cout<<"two!"<<endl;
        }
};

int main(){
    One *o = new Two();
    o->func();
}

为什么 o->func() 上有错误?

我不知道它背后的机制......在我看来,o->func()应该调用派生class中的func(),即public ,所以不会有问题,但它说:

 error: ‘virtual void One::func()’ is private

可访问性检查是根据对象的静态类型进行的。 o 的类型是 One*。这意味着如果 One::func()private,那么 o->func() 将无法编译。

另一方面,根据对象的动态类型,将在 运行 时调用哪个虚拟成员函数(即动态调度)。所以如果One::func()publico->func()会调用Two::func(),因为o指向一个Two.[=30=类型的对象]

对于您的示例代码和用例,使 One::func() private 毫无意义。但请注意,有一个著名的习语叫做 Non-Virtual Interface,它利用了基 class.

private 个虚拟成员函数

其他建议:

  1. 别忘了delete o;
  2. 在基class One中添加一个虚拟析构函数。否则 delete o; 将导致未定义的行为;例如Two 的析构函数可能不会被调用。

    class One {
        public:
            virtual ~One() {}
        // ...
    };
    

子类不能放宽继承限制, 即使 func 是虚拟的,它仍然存在继承限制。

请参阅此答案以了解继承限制的完整视图:

Difference between private, public, and protected inheritance

请检查Access specifiers and virtual functions

来自标准:

§11.5 [class.access.virt] The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.

Access is checked at the call point using the type of the expression used to denote the object for which the member function is called. The access of the member function in the class in which it was defined is in general not known.

如果名称查找确定一个可行函数是虚函数,则在用于命名函数的对象表达式的静态类型范围内检查虚函数的访问说明符。在 运行 时,可以在派生的 class 中使用完全不同的访问说明符定义要调用的实际函数。这是因为'access specifiers'是编译时现象。

由于函数 func() 的访问说明符在 One *o 范围内检查,并且在 class One 中是私有的,因此会产生错误。

如果 Onefunc() 声明为 public,并且 Two 将其声明为私有,则不会出现任何错误。看到这个 Private function invoked and it works. Could any of you reason it please