3

I've tried running the following piece of code. Notice that the function "g" calls the function "f" which is public in X but private in Y.

class X{
    public:
        virtual void f(void){cout<<"From X\n";}
        virtual void g(X* x) { x->f();}
};

class Y: protected X{
    private:
        void f(void){cout<<"From Y\n";}
};

int main() {
    Y y = Y();
    Y *py = &y;
    X* px = py;
    py->g(py);

    return 0;
}

The output is (Notice the inheritance is protected):

prog.cpp: In function ‘int main()’:
prog.cpp:18:10: error: ‘X’ is an inaccessible base of ‘Y’
  X* px = py;
          ^
prog.cpp:7:16: error: ‘virtual void X::g(X*)’ is inaccessible
   virtual void g(X* x) { x->f();}
                ^
prog.cpp:19:10: error: within this context
  py->g(py);
          ^
prog.cpp:19:10: error: ‘X’ is not an accessible base of ‘Y’
prog.cpp:19:10: error: ‘X’ is an inaccessible base of ‘Y’
prog.cpp:18:5: warning: unused variable ‘px’ [-Wunused-variable]
  X* px = py;

If I change the inheritance from protected to public then the code works and I get the following output:

From Y

It seems to me as if the private access restriction of wasn't enforced on the call to function "f" when the inheritance was public (Since Y::f was called from X). Before running this piece of code I thought I should always get a compile time error because of the access restriction (which was proved wrong).

Somehow changing the inheritance from public to protected fixes this and doesn't enable the call to Y::f. Can anyone explain why?

matanc1
  • 6,525
  • 6
  • 37
  • 57
  • possible duplicate of [Inheritance: 'A' is an inaccessible base of 'B'](http://stackoverflow.com/questions/9661936/inheritance-a-is-an-inaccessible-base-of-b) – masoud Oct 13 '13 at 07:42
  • 1
    A bit too language lawyerish for me to answer but I do know you will never get a run time error because of an access restriction. Access applies at compile time only. – john Oct 13 '13 at 07:44
  • It's not. Although that's a good post. – matanc1 Oct 13 '13 at 07:44

1 Answers1

6

There is no breaking of encapsulation: your method is public on X, and an object of class Y "is also" of type X when you use public inheritance.

Overriding in C++ is orthogonal to access rules. You can override a public method with a private method. It is probably bad design, since you can always call it via a reference to the base class.

This means that when you have a pointer to X, only access restrictions of class X apply.

Note that you can override a private method too (see the "Template Method" GOF design pattern)

class X {
public:
    void f () { g (); }

private:
    virtual void g () = 0;
};

class Y : public X
{
private:
    void g () { std::cout << "from X\n"; }
};

Thus, you may want to prefer making the virtual functions as private as you can.

As to why it does not compile when using protected inheritance, well, it is because the inheritance is protected. If Y inherits privately or protectedly from X, then you cannot get a pointer to X with an object of type Y.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197