First of all, your Derived::fun() is also virtual, because if a function in a derived class has the same declaration as a virtual function in the base class, the function in derived class automatically gets virtual, even if that was not explicitly specified.
Secondly, it is completely OK to access private virtual functions via public intermediate functions from the base class, see, for example, this answer and its links, particularly Virtuality by Herb Sutter. A sample code might be like
#include<iostream>
using namespace std;
class Derived;
class Base {
private:
virtual void fun() { cout << "Base Fun"; }
public:
void funInt() { fun(); }
};
class Derived: public Base {
private:
virtual void fun() { cout << "Derived Fun"; }
};
int main()
{
Base *ptr = new Derived;
ptr->funInt();
return 0;
}
So, what happens in your case, I think, is a similar situation: the main is allowed to access ptr->fun(), but due to virtuality this fun() happens to be Derived::fun().
UPD: expanding on a comment
But doesn't this sound a little alarming.. I mean, all the functions
that derive from the Base class, will have their private members
accessible to the friend functions of the Base class
No, not all the functions of Derived will be accessible to the friends of Base, but only those that can be accessible via Base pointer. For example:
class Base {
virtual void fun();
friend int main();
}
class Derived: public Base {
virtual void fun();
virtual void foo();
void bar();
}
only Derived::fun() can be accessed from main:
int main() {
Derived *ptr = new Derived;
Base* baseptr = ptr;
baseptr->fun(); // ok, calls Derived::fun()
baseptr->foo(); // error, no such function in Base
ptr->foo(); // error, foo is private
return 0;
}
Note that virtual function are intentionally extensible, and any override of virtual function in Derived means that that function can be called via Base pointer; this is the main purpose of virtual functions. If Derived makes its overriding function private, it still should be conscious that the function can be accessed via Base pointer, because that is the main idea behind the virtual functions.