1
votes

Possible Duplicate:
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;
}

The output of the program is "D::show() called.", which means the virtual function declared in the private part of class D is invoked. Don't you think it weird? How could a private member of a class be accessed from outside?

3
There are 999999 duplicates of this question. - Puppy
Access specifiers restrict only those accesses that go from the outside of a class. So, if you'd write the fun(D&) or fun(D*) it would not be able to get access to the D::show() using static linking with a concrete sibling class in mind. Using the base class, which has a public member show() you gain the access through the polymorphic call, which goes through the barrier to the sibling's implementation. Ughh! :) I've just tried to explain it in a more literal way. - parallelgeek

3 Answers

6
votes

The crucial part is that your function void fun(B&obj) takes an argument of static type B& (so a conversion happens at the call site; the same happens with B*).

Since B::show is public, your code has no problem calling it. When the compiler looks at how to dispatch the call it sees that show is virtual so it calls D::show. The fact that you could not have called D::show if obj was of type D is irrelevant.

6
votes

Unlike Java, in C++ the access specifier doesn't affect the virtual functions.
'Access specifier' is a compile time check which is made on the class method with respect to static type of the handle. e.g. in your code obj is of type B and B::show() is public; hence the code is legal.
obj may refer dynamically to some other type than B.

Remember that virtual function dispatch is a runtime phenomena. (In Java it would have given a runtime error.)

B::show() is public and once it's invoked, the virtual functionality will kick in and call the appropriate object's function.

If you try calling D::show() directly then you will get the expected compiler error.

2
votes

It's not weird. In B, the method is public. You can call show() on a B object.

It's just that the method gets dispatched to an extending class.