6

The method fun() in the Derived class is private. When we call the function ptr->fun() through run time polymorphism, it is executing. But this violates the encapsulation property of the Derived class.

#include<iostream>
using namespace std;

class Derived;

class Base {
private:
    virtual void fun() { cout << "Base Fun"; }
friend int main();
};

class Derived: public Base {
private:
    void fun() { cout << "Derived Fun"; }
};

int main()
{
Base *ptr = new Derived;
ptr->fun();
return 0;
}

Can anyone please explain what is happening?

Green goblin
  • 9,898
  • 13
  • 71
  • 100
Haris
  • 12,120
  • 6
  • 43
  • 70
  • friends have acces to private members. You declare the main as friend, so there is access to private members. (why you did this is a miracle to me) – 463035818_is_not_an_ai Jul 22 '15 at 09:45
  • @tobi303, friend has access to private of `Base` not `Derived` and the `fun()` being called when the program is run is `fun()` of the `Derived` class.. BTW i was playing around with c++ concepts, so came across this.. nothing practical.. – Haris Jul 22 '15 at 09:48

3 Answers3

2

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.

Community
  • 1
  • 1
Petr
  • 9,812
  • 1
  • 28
  • 52
  • ook. 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. – Haris Jul 22 '15 at 10:18
  • @haris, no! Only the `virtual` functions that have already been there in `Base`! I will expand the answer in a minute. – Petr Jul 22 '15 at 10:19
  • 1
    @haris, expanded the answer – Petr Jul 22 '15 at 10:29
  • nice.. understood.. :) – Haris Jul 22 '15 at 10:47
1

Friend functions never take part in inheritance.

What is happening here?
When virtual method is defined in Base class, a virtual table is createdwhich contains address of fun method of Base class. And since, Derived class inherits it, the VTABLE also contains the address of Derived class fun method. Now, since main is the friend function of Base class, compiler allows access of its members to main method irrespective of their access specifier. Hence, main gets the address of Derived::fun and Derived class fun gets called at runtime.

Green goblin
  • 9,898
  • 13
  • 71
  • 100
0

This is happening because you have declared funas virtual. At runtime when the vtable is searched, it finds the entry for Derived::fun() and hence jumps to the address.

However the friend functions does not get inherited, you can check using this.

class Base {
private:
    virtual void fun() { cout << "Base Fun"; }
    friend int main();
    int z = 20;
};

class Derived : public Base {
private:
    void fun() { cout << "Derived Fun"; }
    int m = 10;
};

int main()
{
    Base *ptr = new Derived;
    ptr->z = 10; //Accepted
    ptr->m = 5; //error
    return 0;
}

Here private member of Derived m is not accessible to main.

Nishant
  • 1,635
  • 1
  • 11
  • 24
  • i didn't get you, the program is accessing the private function of Derived class from the `main()` function.. how does making `fun()` function in Base class virtual effects that.. – Haris Jul 22 '15 at 09:50
  • @Nishant i doubt vtables work that way.. see this description http://imgur.com/6e23Roa – Haris Jul 22 '15 at 10:01
  • @DenisZaikin yes, obviously it will be "Base Fun", because ptr is pointing to object of derived, which has subobject of base. – Nishant Jul 22 '15 at 10:04
  • @haris deleted my comment, it was wrongly put, what i meant to say is that since private functions can access private virtual function and in your case, just because of method is declared virtual, the Derived:Fun gets called. As you can see in my example, not all private members can be accessed, only virtual. – Nishant Jul 22 '15 at 10:27