1

可能重复:
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;
}

程序的输出是“D::show() called.”,表示调用了类 D 的私有部分中声明的虚函数。你不觉得很奇怪吗?如何从外部访问类的私有成员?

4

3 回答 3

6

与 Java 不同,在 C++ 中,访问说明符不会影响virtual函数。
“访问说明符”是针对句柄类型对类方法进行的编译时检查。static例如,在您的代码obj中是类型B并且B::show()public;因此该代码是合法的。
obj可以动态引用其他类型而不是B.

请记住,virtual函数分派是一种运行时现象。(在 Java 中它会给出运行时错误。)

B::show()public并且一旦它被调用,该virtual功能将启动并调用适当的对象的函数。

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

于 2012-04-18T11:32:29.007 回答
6

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

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

于 2012-04-18T11:36:00.063 回答
2

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

只是该方法被分派到扩展类。

于 2012-04-18T11:31:53.517 回答