Search code examples
c++classinheritanceaccess-controlinjected-class-name

Private inheritance visibility/access in C++


Why does an interface have a special visibility in a method due to a private inheritance?

Note that a global specifier :: is required in my derived class.

I don't understand why a method inherits some kind of visibility due to private inheritance. It's totally reasonable that Derived class doesn't have access to Control. But why doesn't it have access through a member either?

class Control
{
public:
    void ModifySomething();
};

class Base : private Control
{
private:
    virtual void Update( Control& i_control );
};

class Derived : public Base
{
private:
    // ----------↓↓
    void Update( ::Control& i_control ) override;
};

Note: I understand we could fix this by composition. But I would like to know why it's defined like that in C++. Could we break const-ness or something?


Solution

  • According to the C++ 17 Standard (14.1 Access specifiers)

    5 [ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. — end note ]

    And there is an example similar to your code snippet.

    [Example:

    class A { };
    class B : private A { };
    class C : public B {
      A* p; // error: injected-class-name A is inaccessible
      ::A* q; // OK
    };
    

    — end example ]

    That is the injected class name of the private base class within the derived class definition hides the name of the base class defined in the namespace. And this injected name is private. So the derived class does not have an access to this private injected name.