2

like this code

class Try
{
public:
    Try() = default;
    int i = 0;
};

class B1 : private Try
{
public:
    B1() = default;
    using Try::Try();
    using Try::i;
};

class C1 : public B1
{
public:
    Try a; //tell me:'Try' is a private member of 'Try'
    
    void print()
    {std::cout << i << std::endl;}
    //Access to this I is allowed;
};

the Try a is a local object , not a part of C1, why error?

As long as it is a direct base class of private inheritance, can it not be possible to define an indirect base class object in its derived class? Is it because the constructor cannot be used or is it for other reasons?

Jodocus
  • 7,493
  • 1
  • 29
  • 45
Nater
  • 165
  • 7

1 Answers1

3

the Try a is a local object , not a part of C1, why error?

By writing Try a; in the context of class C1, the name lookup will generally always scan from local to global scope. The first match thus will be B1::Try, which is, due to the private inheritance, inaccessible for C1.

The fix is easy, just hint the compiler the name you "really" mean, i.e. by writing e.g. ::Try a;.

Jodocus
  • 7,493
  • 1
  • 29
  • 45
  • I understand that the class of c1 belongs to the local scope. I still don't understand why the local action cannot define the object? Is it because of private inheritance? – Nater Jan 07 '21 at 10:45
  • @Nater Yes, you access `Try` "through the lens" of `B1`, as `B1` is the next context for the compiler to look for the name `Try`, which is not available in `C1`. However, `B1::Try` does indeed exist (due to inheritance), but it is inaccessible for `C1` (as the inheritance is private), so from outside of `B1`, it is invalid to assert that `B1` is derived from `Try`. The compiler does not care whether `B1::Try` is accessible or not, it found a name that works and stops the search for another `Try`. That's why you must access `Try` on a global level by `::Try` to give a hint. – Jodocus Jan 07 '21 at 10:53
  • I have some understanding, but I still have a question: as long as it is private inheritance, is it impossible to define an object of an indirect base class in its derived class? Although the constructor of the direct base class is declared as public, I made some changes in the code – Nater Jan 07 '21 at 11:00
  • @Nater No, it's not impossible. As I've already written, if you access it by `::Try a;`, you can define an object of an indirect base class type when private inheritance is in place. By making the constructor accessible you still will not be able to use `B1::Try`, as from the view point of access control, any assumption of inheritance is forbidden (due to privateness). – Jodocus Jan 07 '21 at 11:11
  • @Nater - No - as this answer says - private inheritance does not prevent using an instance of the base class as a member of the derived class. It is necessary to ensure, in context of `C1`, that the type of the member is named correctly (i.e. that the member is specified as `::Try a` rather than `Try a`). `::Try` is the fully qualified name of `Try`, in your example. – Peter Jan 07 '21 at 11:12
  • @Jodocus I still cannot understand why indirect base class objects cannot be defined in the local scope? Is there any underlying reason? Or is it just a rule of C++ syntax? – Nater Jan 07 '21 at 17:47
  • @Nater I can only repeat myself, there is nothing more to understand than I've written down (and I doubt that the exact wording of the standard would help you any further). You have to either accept that or switch to another programming language. – Jodocus Jan 08 '21 at 09:18