7

Possible Duplicate:
C++: overriding public\private inheritance

class base {
public:
  virtual void doSomething() = 0;
};

class derived : public base {
private:   // <-- Note this is private

  virtual void doSomething()
  { cout << "Derived fn" << endl; }
};

Now if I do the following:

base *b = new derived;
b->doSomething();    // Calls the derived class function even though that is private

Question:

  1. It's able to call the derived class function even though it is private. How is this possible?

Now if I change the inheritance access specifier from public to protected/private, I get a compilation error:

'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

Note: I am aware of the concepts of the inheritance access specifiers. So in the second case as it's derived private/protected, it's inaccessible. But I wonder about the answer to first question. Any input will be highly appreciated.

Hari
  • 1,561
  • 4
  • 17
  • 26
user1706047
  • 369
  • 3
  • 7
  • 19

3 Answers3

7

Access control is implemented at compile time, not run-time, while polymorphism (including the use of virtual functions) is a run-time feature.

jogojapan
  • 68,383
  • 11
  • 101
  • 131
Healer
  • 290
  • 1
  • 7
  • 1
    I think he wants to know why the access specifier works that way rather than knowing what is the source of the error. – Hossein Nov 29 '12 at 05:15
7

In the first case the access check is done (as it is always done) on the static type that the call is made through. The static type of *b is base, and in that case doSomething() is public.

C++03 11.6 "Access to virtual functions" says:

The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [Example:

class B {
public:
    virtual int f();
};

class D : public B {
private:
    int f();
};

void f()
{
    D d;
    B* pb = &d;
    D* pd = &d;

    pb->f(); //OK:B::f()is public,
             // D::f() is invoked
    pd->f(); //error:D::f()is private
}

—end example]

Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.

Keep in mind especially that "the access of the member function in the class in which it was defined (D in the example above) is in general not known". In general, at the point in your example where b->doSomething(); is called, the compiler may have no knowledge at all about derived (or child), much less whether or not the access to derived::doSomething() is private.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

Private functions are meant to be hidden from the outside world and from the derived classes. Although you are overriding the access specifier of the parent's DoSomething and making it private, you are instantiating a base class; so in the first case, you can call base's DoSomething as it is public. This scenario can be used if you want to stop people deriving from your derived class.

In the second case, the private access specifier causes the base's members not to be exposed to the users of the derived class, which effectively makes the derived class useless.

Hossein
  • 4,097
  • 2
  • 24
  • 46
  • 1
    The OP said quite clear **It's able to call the derived class function**. Your speculation about **you can call base's DoSomething as it is public** is wrong based on given example and is not an answer on question 1. – StahlRat Oct 16 '14 at 15:30