Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with nested class inheritance

Tags:

class A {}; class B : private A {}; class C : private B { public:     class D : private A {}; // Error here }; 

This code gives the following error (in VS 2013):

nested.cpp(8) : error C2247: 'A' not accessible because 'B' uses 'private' to inherit from 'A'

It gets fixed if I change the definition of D like this:

class D : private ::A {}; 

Is this correct behavior, and if so why?

At first I thought it was because C inherits privately from B which would hide the base classes. But if I eliminate the "middle man" class B and just use this:

class A {}; class C : private A { public:     class D : private A {}; }; 

The error goes away.

like image 485
user1610015 Avatar asked Dec 09 '16 07:12

user1610015


People also ask

Can nested classes be inherited?

A static nested class can inherit: an ordinary class. a static nested class that is declared in an outer class or its ancestors.

How do you inherit a nested class in C++?

A nested class may inherit from private members of its enclosing class. The following example demonstrates this: class A { private: class B { }; B *z; class C : private B { private: B y; // A::B y2; C *x; // A::C *x2; }; }; The nested class A::C inherits from A::B .

Can we inherit nested class in Java?

A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.

Can we inherit a nested class in C#?

The scope of a nested class is bounded by the scope of its enclosing class. By default, the nested class is private. In C#, a user is allowed to inherit a class (including nested class) into another class.


2 Answers

Quote from cppreference:

A name that is private according to unqualified name lookup, may be accessible through qualified name lookup

With that in mind lets see how the unqualified name lookup would work for the first example:

class A {};  class B : private A {};  class C : private B { public:     class D : private A {}; // Error here }; 
  1. A is looked up within the scope of C. Had it been defined there, there would be no problem.
  2. It figures out A is privately inherited by it's base (private) class B and hence throws a compiler error. Clang says:
     note: constrained by private inheritance here: class B : private A {}; 

Again, as per the quote it should work, if you use fully qualified name, like you have shown

class D : private ::A {}; 

And as for your last example:

class A {};  class C : private A { public:     class D : private A {}; }; 

It works because, the name lookup works for all names that are part of the same class. To quote from cppreference again:

All members of a class (bodies of member functions, initializers of member objects, and the entire nested class definitions) have access to all the names to which a class can access.

like image 117
Arunmu Avatar answered Sep 22 '22 16:09

Arunmu


It's a matter of scopes during name lookup:

  • When you use ::A it's a fully qualified name, thus you are explicitly referring to the global namespace and picking A up from there.

  • When you inherit from A, C (let me say) sees A and you can directly refer to the A name within C with an unqualified name.

  • When you inherit from B, C sees B and A is private in its scope. It's private, but it exists. Because A is an unqualified name and is looked for first of all in that scope, it happens to be found and unaccessible, thus the error.

like image 28
skypjack Avatar answered Sep 23 '22 16:09

skypjack