1

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?

Community
  • 1
  • 1
JDein
  • 295
  • 2
  • 9
  • 5
    There are 999999 duplicates of this question. – Puppy Apr 18 '12 at 11:31
  • 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 Apr 18 '12 at 11:41

3 Answers3

6

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.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • "the access specifier doesn't affect the virtual functions" you should probably edit this part. I get what you mean, but it can be confusing for an untrained eye. – Luchian Grigore Apr 18 '12 at 11:50
6

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.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • I found that if I place the virtual function show() in private part of the base class B, the program will fail to compile, alerting that the virtual function is private in the base class even if the counterpart in the derived class is declared as public: #include using namespace std; class A{ private: virtual void function(){cout<<"void A::function() get invoked."<function(); ao.function(); } – JDein Apr 20 '12 at 06:31
2

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.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625