C++中的公共虚函数派生私有

2021-12-17 00:00:00 inheritance c++ virtual-functions

我试图弄清楚当派生类将虚函数声明为私有时会发生什么.下面是我写的程序

I was trying to figure out what happens when a derived class declares a virtual function as private. The following is the program that I wrote

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void func() {
        cout<<"A::func called"<<endl;
    }
    private:
};
class B:public A
{
    public:
    B()
    {
        cout<<"B constructor called"<<endl;
    }
    private:
    void func() {
        cout<<"B::func called"<<endl;
    }
};
int main()
{
    A *a = new B();
    a->func();
    return 0;
}

令人惊讶的(对我而言)输出是:

Surprisingly (for me) the output was:

B constructor called
B::func called

这是否违反了为该功能设置的私有访问权限.这是预期的行为吗?这是标准的解决方法还是漏洞?通过 VTABLE 解析函数调用时是否绕过访问级别?

Isn't this violating the private access set for that function. Is this the expected behavior? Is this is a standard workaround or loophole? Are access levels bypassed when resolving function calls through the VTABLE?

对此行为的任何见解都会非常有帮助.

Any insight in to this behavior would be greatly helpful.

进一步提到,私下覆盖虚拟成员会阻止更多的类继承它.即使这样也有问题.修改上面的程序,包括:

Further it was mentioned that a privately overriding a virtual member would prevent further classes from inheriting it. Even this is having problems. Modifying the above program to include:

class C: public B
{
    public:
    void func() {
        cout<<"C::func called"<<endl;
    }
};

和主测试程序:

int main()
{
    A *a = new C();
    a->func();
    return 0;
}

输出为:

C::func called

推荐答案

行为是正确的.每当您将函数声明为虚拟"时,您都会指示编译器生成虚拟调用,而不是直接调用此函数.每当您覆盖后代类中的虚函数时,您就指定了该函数的行为(您不会更改那些依赖父类"接口的客户端的访问模式).

The behavior is correct. Whenever you declare your function as "virtual", you instruct the compiler to generate a virtual call, instead of the direct call to this function. Whenever you override the virtual function in the descendant class, you specify the behavior of this function (you do not change the access mode for those clients, who rely on the "parent's" interface).

更改子类中虚函数的访问模式意味着您希望对那些直接使用子类(依赖子类"接口)的客户隐藏它.

Changing the access mode for the virtual function in the descendant class means that you want to hide it from those clients, who use the descendant class directly (who rely on the "child's" interface).

考虑这个例子:

void process(const A* object) {
   object->func();
}

"process" 函数依赖于父级的接口.它预计适用于从 A 公共派生的任何类.您不能从 A 公共派生 B(说每个 B 都是 A"),而是隐藏其接口的一部分.那些期望A"的人必须得到一个功能齐全的A".

"process" function relies on the parent's interface. It is expected to work for any class, public-derived from A. You cannot public-derive B from A (saying "every B is A"), but hide a part of its interface. Those, who expect "A" must receive a fully functional "A".

相关文章