1

Why I am getting access-specifier error (private-member) for the following piece of code?

#include<iostream>
using namespace std;

class Derived;

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

class Derived: public Base {
public:
    void fun() { cout << "Derived Fun"; } //this should be called
};

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

Here, fun() of derived class should be called and since it is public, there should be no error.

2 Answers 2

6

According to the standard (N4140):

11.5 Access to virtual functions

1 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 ]

BTW, in general case, during compilation it is not possible to know which class is going to be called at run-time.

Consider

Base *ptr = GetBaseOrDerivedObject();
ptr->fun();

where GetBaseOrDerivedObject, depending on concrete run-time situation, can return a poiner to an object of type Base or Derived.

Sign up to request clarification or add additional context in comments.

2 Comments

I seriously didn't get it. As per late resolution, vptr must be pointing to the vtable of derived class. Since derived class fun() is public, it must be called without any hassle. How does base class comes into picture here? Or I understood late binding incorrectly?
The check is done at compile time, not at run time, so it is not related to late binding.
0

Here, fun() of derived class should be called and since it is public, there should be no error.

Unfortunately, this is not true.

This works:

 Derived *ptr = new Derived;
 ptr->fun();

This doesn't work:

 Base *ptr = new Derived;
 ptr->fun();

The reason is simple: Base has no public member named fun, so you cannot access it through a pointer to Base.
You are allowed to set your own visibility specifier for an overridden member method in the derived class, but this does not magically promote the specifier of the base class.


There exists a well known idiom called NVI (non virtual interface) that is mostly based on this pattern (a private virtual member method in the base class).
You can imagine it as a refinement of the template method pattern, even though to be honest this is not true at all.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.