0
class A 
{
    public:
    virtual void fun() 
    { 
        cout << "A Fun"; 
    }
};

class B:public A
{
    private:
    void fun() 
    { 
        cout << "B Fun"; 
    }
};

class C:public B{};

int main()
{

   //Case1       

   A *ptr = new C();
   ptr->fun();
   /*
         OUTPUT : B Fun
   */

   //Case 2

   B *ptr2 = new C();
   ptr2->fun();
   /*
        ERROR:
        main.cpp: In function ‘int main()’:
        error: ‘virtual void B::fun()’ is private within this context
            ptr2->fun();
                  ^
        note: declared private here
             void fun()
              ^~~ 
   */
   return 0;
}

In case 1 : I am able to call the private fun() in class B , but why I am not able to call the private fun() in case 2? Why fun() in class B is having two different kind of behaviour? I mean to say that when I make pointer of type A then fun() of class B act as public function but when I make pointer of type B then fun() of class B act as private function.

Anurag Singh
  • 127
  • 1
  • 4
  • Better question - change that `new C()` to a `new B()` on the first example - it will still work! – kabanus Aug 05 '18 at 20:52
  • 1
    Related - https://stackoverflow.com/questions/484592/overriding-public-virtual-functions-with-private-functions-in-c – kabanus Aug 05 '18 at 20:58
  • Access control applies to **declarations**. It doesn't matter if they refer to virtual functions. – curiousguy Aug 05 '18 at 21:06

2 Answers2

1

In case 1 : I am able to call the private fun() in class B [...]

No, you are not being able to call / are not calling a private method in a class B. You are calling a public method from class A that happens to be overriden in the child class.

This is especially useful when unit testing a private method. You simply make your class inherit from a dummy base class that declares the method of interest as public and (possibly pure) virtual.

Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • Then why is it not working in case 2? – Anurag Singh Aug 05 '18 at 20:58
  • 1
    Because you cannot call a `private` method outside of the class within non-`friend` scope. You need to understand the difference between *calling a private method* and *calling a public method which results in calling a private method*. – Fureeish Aug 05 '18 at 21:01
  • If I remove fun() from class B then calling ptr2->fun() will invoke A::fun() where ptr2 is of type B. So we can reach to A::fun() in this case. So whats the difference that restrict us to call the public method (of class A) which results in calling a private methodof class B) – Anurag Singh Aug 05 '18 at 21:07
  • Nothing restricts you to do so, but to call a public method of a base class with a derived class pointer, you'd have to upcast that pointer using `static_cast<>` first, like so: `static_cast(ptr2)->fun()`. – Fureeish Aug 05 '18 at 21:21
1

Private-ness and public-ness is a purely compile time property of a member of a class/struct. The compiler checks if you have access to a member while compiling the code.

So in your code:

B b;
b.fun(); // Error! B::fun is private in this context!

A& a = static_cast<A&>(b); // `a` is a reference to `b`
a.fun(); // okay, A::fun is public.
         // It just so happen that A::fun is virtual,
         // So the function dispatched at runtime will be B::fun
         // But the compiler has no mean to check this.

The behavior at runtime is determined if the function has been overridden, and only if the function A::fun is virtual. By overridding a virtual function, you must agree that expression using A will be dispatched to B, regardless what restrictions is on B. Code calling A::fun polymorphically must work with any subclasses, because code that deal with the base class cannot know the derived classes.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141