5

I came across this code written in C++ :

#include<iostream>
using namespace std;

class Base {
public:
    virtual int fun(int i) { cout << "Base::fun(int i) called"; }
};

class Derived: public Base {
private:
    int fun(int x)   { cout << "Derived::fun(int x) called"; }
};

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

Output:

 Derived::fun(int x) called 

While in the following case :

#include<iostream>
using namespace std;

class Base {
public:
    virtual int fun(int i) { }
};

class Derived: public Base {
private:
    int fun(int x)   {  }
};
int main()
{
    Derived d;
    d.fun(1);
    return 0;
} 

Output :

Compiler Error.

Can anyone explain why is this happening ? In the first case , a private function is being called through an object.

Coding Mash
  • 3,338
  • 5
  • 24
  • 45
h4ck3d
  • 6,134
  • 15
  • 51
  • 74
  • 5
    "Without using friend" - learn C++ yourself and you won't need your friend to code it for you. (JK) –  Sep 22 '12 at 19:43
  • @H2CO3 OP meant friend keyword :) – PiotrNycz Sep 22 '12 at 19:46
  • `d.fun(1)` isn't a virtual function call, but `ptr->fun(10)` is. – Zyx 2000 Sep 22 '12 at 19:46
  • @Zyx2000 Why is that so ? Derived also has fun() of Base isn't it? – h4ck3d Sep 22 '12 at 19:48
  • You have `virtual int` but an integer is not being returned in those functions.. – David G Sep 22 '12 at 19:48
  • @sTEAK. Google for **late binding**. – Bartek Banachewicz Sep 22 '12 at 19:48
  • 1
    @sTEAK. calls through pointers will be virtual, calls directly on the object won't. The exact type of d will always be known at the point of the call. – Zyx 2000 Sep 22 '12 at 19:49
  • @BartekBanachewicz I know , late binding / run time binding / dynamic binding. What am asking is , when we use . (dot) operator then late binding doesn't take place ? Does it take place in case of pointers only ? – h4ck3d Sep 22 '12 at 19:50
  • @Zyx2000 Thanks that clarifies it. – h4ck3d Sep 22 '12 at 19:50
  • @PiotrNycz If I didn't know C++, that comment of mine wouldn't be funny... –  Sep 22 '12 at 19:51
  • This will make it compile: ((Base &)d).fun(1); – Jeremy Friesner Sep 22 '12 at 19:55
  • @H2CO2 at least I learnt what (JK) means :) I realized too late that it was funny ... I should go sleep, it's too late... – PiotrNycz Sep 22 '12 at 19:58
  • @Zyx2000 You shall make your comment an answer and I will accept that. – h4ck3d Sep 22 '12 at 19:59
  • 1
    @sTEAK : All this has nothing to do with use of `->` or `.` operators. It only has to do with the type you use to call the method: If you call the method through `Base`, it will compile as the method `Base::fun` is public. If you call the method through `Derived`, it will fail as `Derived::fun` is private. . . Now, `fun` is virtual, meaning that calling it means, by default, dynamic binding... Unless the compiler can guarantee the exact type of the object at compile time. In that case, the call will be optimized, to be statically resolved to the right method. – paercebal Sep 22 '12 at 20:03
  • possible duplicate of [Why can I access a derived private member function via a base class pointer to a derived object?](http://stackoverflow.com/questions/3610936/why-can-i-access-a-derived-private-member-function-via-a-base-class-pointer-to-a) – Bo Persson Sep 22 '12 at 20:12

2 Answers2

4

Because in the first case you're using declaration from Base, which is public, and the call is being late-bound to the Derived implementation. Note that changing the access specifier in inheritance is dangerous and can nearly always be avoided.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
3

Polymorphism is happening in the first case. It causes dynamic or late binding. And as mentioned in the second answer, it can become quite dangerous at times.

You cannot access the private interface of a class from the outside of class definition directly. If you want to access the private function in the second instance without using a friend function, as title of your question implies, make another public function in your class. Use that function to call this private function. Like this.

 int call_fun (int i) ;

Call the fun() from inside it.

int call_fun (int i)
{
  return fun (i) ;  //something of this sort, not too good
}

The functions like this which are used just to call another function are known as wrapper functions.

Making friends is also not advisable always. It is against the principle of information hiding.

Coding Mash
  • 3,338
  • 5
  • 24
  • 45
  • Though I agree with Making friends is also not advisable always. I definitely think It is against the principle of information hiding is wrong. Friendship does not break encapsulation in increases it. The alternative to friendship is to expose the data to more systems (which does break encapsulation). Friendship increases encapsulation at the cost of tightly coupling the friend and thus making it part of the interface. http://programmers.stackexchange.com/a/99595/12917 – Martin York Sep 22 '12 at 20:42
  • I agree with that. But it generally depends upon the approach, the situation and the problem in hand. As in this one, friendship can easily be avoided. – Coding Mash Sep 23 '12 at 04:45