为什么仍然可以访问成员函数,即使它被声明为"私有"?

JDe*_*ein 1 c++ virtual-functions access-specifier private-members

可能重复:
公共虚拟函数在C++中派生为private

class B
{
    private:
    int b;
    public:
    B(int i);
    virtual void show()
    {
        cout<<"B::show()called. "<<b<<endl;
    }
};

B::B(int i=0)
{
    b=i;
}

class D:public B
{
    private:
    int d;
    void show()
    {
        cout<<"D::show() called. "<<d<<endl;
    }
    public:
    D(int i, int j);
};

D::D(int i=0, int j=0):B(i)
{
    d=j;
}

void fun(B&obj)
{
    obj.show();
}
/*if I redefine fun() as follow, the result would be the same
void fun(B*obj)
{
obj->show();
}
*/
int main()
{
    D *pd=new D(5,8);
    fun(*pd);     //K
    delete pd;
}
Run Code Online (Sandbox Code Playgroud)

程序的输出是"D :: show()调用.",这意味着调用在类D的私有部分中声明的虚函数.你不觉得这很奇怪吗?如何从外部访问班级的私人成员?

iam*_*ind 6

与Java不同,在C++中,访问说明符不会影响virtual函数.
'访问说明符'是一个编译时检查,它是static根据句柄类型在类方法上进行的.例如,在你的代码中obj是类型B而且B::show()public; 因此代码是合法的.
obj可以动态地引用其他类型的B.

请记住,virtual函数调度是一种运行时现象.(在Java中,它会产生运行时错误.)

B::show()是的public,一旦它被调用,virtual功能将启动并调用适当的对象的功能.

如果您尝试D::show()直接调用,那么您将获得预期的编译器错误.


Jon*_*Jon 6

关键部分是你的函数void fun(B&obj)采用静态类型的参数B&(因此转换发生在调用站点;同样的情况发生B*).

由于B::show 公开的,您的代码调用它没有问题.当编译器着眼于如何调度呼叫它认为showvirtual这样调用D::show.你无法调用D::showif obj是类型的事实D是无关紧要的.