Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is friend function getting inherited here?

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?

like image 665
Haris Avatar asked Jul 22 '15 09:07

Haris


1 Answers

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.

like image 144
Petr Avatar answered Sep 30 '22 00:09

Petr