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

时间:2012-04-18 11:30:18

标签: c++ virtual-functions private-members access-specifier

  

可能重复:
  Public virtual function derived private in C++

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;
}

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

3 个答案:

答案 0 :(得分:6)

与Java不同,在C ++中,访问说明符不会影响virtual函数 “访问说明符”是编译时检查,它是在类方法上根据句柄的static类型进行的。例如在您的代码obj中,B类型为B::show()publicobj;因此代码是合法的 B可以动态引用除virtual之外的其他类型。

请记住,B::show()函数调度是运行时现象。 (在Java中,它会产生运行时错误。)

publicvirtual,一旦调用,D::show()功能将启动并调用相应对象的功能。

如果您尝试直接调用{{1}},那么您将收到预期的编译器错误。

答案 1 :(得分:6)

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

由于B::show 是公开的,因此您的代码调用它没有问题。当编译器查看如何分派调用时,它会看到showvirtual,因此它会调用D::show。如果D::show类型为obj,则无法调用D这一事实无关紧要。

答案 2 :(得分:2)

这并不奇怪。在B中,该方法是公开的。您可以show()对象上调用B

只是将方法分派到扩展类。