Class A not visible in class C but visible in main. Why? - c++

class A {};
class B : private A {
};
class C : public B {
public:
void f() {
A a; // This line causes error, but works when it is in main() function
}
};
int main()
{
C c;
// A a; --> This line works
return 0;
}
I am guessing this has something to do with B inheriting privately from A but cannot put my finger on it.
EDIT: Error is "class A is not visible". Compiled with g++.

name lookup is separate from access checking. and when you inherit from a class, that class' name is injected into the inheriting class' scope. so in class C you pick up the name A but it's not accessible.
one solution is to write ::A a; instead of A a;.

While Alf's answer is correct, I feel that it could be made a bit clearer (or maybe more confusing, who knows). The name of a class is injected into the scope of the class itself. As he mentions access specifiers are only checked after lookup finds what the identifier means. In the code in questions:
class A {};
class B : private A {};
struct C : public B {
void f() {
A a; // This line causes error, but works when it is in main() function
}
};
When processing C::f the compiler sees the identifier A and tries to resolve it. It searches in the scope of C and it is not present, it moves up the hierarchy and does not find it in B, but it finds it inside the base type A (lookup resolves the unqualified A to be ::A::A). In this context the identifier A is resolved to the injected name A inside the base class A of my base class B and access specifiers are checked. The compiler checks whether it can access my base class B, and then whether it can access it's base class A but this one is inaccessible due to the private inheritance and complains that you cannot access the nested name A inside A.
By providing the extra qualification ::A you are directing lookup. In this case, it will find the type A in the global namespace, which is perfectly accessible and it will compile.

Related

How to call a hidden method from two times inherited base class in C++?

Consider a class D inherited from two classes B and C, each of which inherits not-virtually class A. There is a method f in A, and the same named method in B hiding the method from A. I would like to call A::f() from B-base class of D object as follows:
struct A { void f() {} };
struct B : A { void f() {} };
struct C : A {};
struct D : B, C {};
int main() { D{}.B::A::f(); }
Unfortunately, it works only in MSVC, while both GCC and Clang produce the error:
error: 'A' is an ambiguous base of 'D'
demo: https://gcc.godbolt.org/z/jY3v876hK
It looks like GCC/Clang accept but completely ignore B:: prefix in B::A::f(). Are they right in doing so according to the standard?
Are they right in doing so according to the standard?
Yes. The nested name specifier in A::, B::A, or D::B::A all serve the same purpose, to name the class A.
[basic.lookup.classref]
4 If the id-expression in a class member access is a qualified-id of the form
class-name-or-namespace-name::...
the class-name-or-namespace-name following the . or -> operator is first looked up in the class of the object expression ([class.member.lookup]) and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression.
The nested name specifier does not name "a path" to the member, it names a base of D. And to name A results in ambiguity.
Other answers show why the compiler is correct.
In order to achieve what you want, you can do:
int main() { static_cast<B&&>(D{}).A::f(); }
It's a bit ugly, though.
https://gcc.godbolt.org/z/Mzs8rsdf5

No use of base object allowed in private inheritance

I am using private inheritance, and I am surprised to see that in the derived class use of any base object is not allowed.
class A;
class B : private A;
class C : public B;
C::method_1()
{
A* a; // Temporary "A" object for local computation
}
This has nothing to do with inheritance. I don't want to access any this->base method!
This configuration provide a C2247 error in Visual Studio (" 'A' not accessible, because 'B' use 'private' to inherit from 'A' ").
Change this:
A* a;
to this:
::A* a;
since C inherits from B, and B from A, thus you need the scope resolution operator to do the trick.
Instead of starting at the local scope which includes the class parents, ::A starts looking at the global scope because of the ::.
From the Standard:
11.1.5 Acess Specifiers
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.
ISO C++: 11.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 the example from the standard:
class A { };
class B : private A { };
class C : public B {
A* p; // error: injected-class-name A is inaccessible
::A* q; // OK
};
N3797 Working Draft, Standard for Programming Language C++

C++ inheritance - ambiguous Function

I've got an Inheritance problem:
Let's say I've got
class Time{
protected:
void foo();
};
and also
class Base: private Time{
void foo1(){ foo(); }
};
class Child: public Base, private Time{
void foo2(){ foo(); }// here my compiler says that foo is ambiguous
};
why is foo() ambiguous, if the inheritance of Time in Base is private?
PS.
Just&only for those who need to see the full code, here is the GitHub Project:
https://github.com/huntekah/Interior_decorator-OpenGL_Project/blob/master/Grafika-OpenGL/Interior_decorator/Display.cpp#L133
class Time( utilities directory ) is inherited by ControlObjects and ControlCamera, both of which are the base for Controls. Display inherits Controls , and additionally Time. commented line shows a place where SetDeltaTime() is ambiguous;
there's another error in your code: class base inherits privately from class Time and class Child inherits again privately from class time!!!
the law of inheritance:
class Time
{};
class Base : private Time
{};
class Child : public Base, private Time
{};
Base has a copy of class Time because it inherits from it.
child has a copy of class Base because it inherits from it.
*** Child has a copy of class Time because its parents (Base) has this copy.
if Child tries to inherit explicitly from class Time will issue a compile-time-error: error C2584: 'Child' : direct base 'Time' is inaccessible; already a base of 'Base'
Preliminary remarks
Your code snippet doesn't compile for another reason: Base has no access to Time's foo() as it is a private member. So the foo1() causes an error, before you have the reported ambiguity.
If you change Time to make its member protected, then you can reproduce your error exactly as you describe:
class Time{
protected:
void foo();
};
What's wrong here ?
Base privately inherits Time, so that it's members are not expected to be visible to the outside world.
But what could be true for the external world is not true for derived classes. The name lookup rules in the case of derivation say that first the name is looked up in the class hierarchy, then overloading is applied, than only is access control carried out:
10.2/1 Member name lookup determines the meaning of a name (id-expression) in a class scope. Name lookup can result in an
ambiguity, in which case the program is ill-formed. For an
id-expression, name lookup begins in the class scope of this; for a qualified-id, name lookup begins in the scope of the
nested-name-specifier. Name lookup takes place before access
control.
10.2/8 If the name of an overloaded function is unambiguously found, overloading resolution also takes place before access control.
Ambiguities can often be resolved by qualifying a name with its class
name.
As you use multiple inheritance:
Time
:
:
Base Time
\ :
\ :
Child
So you inherit twice a foo(), once via private inheritance and onve via public. This ambiguity makes the name foo in foo2() ambiguous according to the standard, and before access is verified, making your code invalid.
Note that Child sees 2 foo() but ironically can't use none of them: both come via private inherited. So even if you'd resolve the ambiguity, you'd get another error message about accessibility.

C++: How to inherit from enclosed class

I would like to have a class inherit from its enclosed class, as in:
class A : public A::B {
public:
class B {};
};
However, the compiler complains that A::B is not defined:
error: expected class-name before '{' token
class A : public A::B {
That is, A::B won't be usable until the definition of A is complete.
I have tried to preface the above with
class A;
class A::B;
But it doesn't help. How can I get this declared and defined correctly?
Note: Essentially, I am trying to do the opposite of this question.
At the point where you specify the inheritance, the inner class is not yet know. Thus you can't do that. But if the point is to limit the scope, then just use a namespace, e.g. call it detail or implementation.
This is not possible, there is no way to declare inner class without defining the outer class.

Unintuitive nested class inheritance

Is the following code valid with C++ standard? It's strange that C::B would work because struct B is in A's namespace. But it does compile fine with gcc.
struct A { struct B {}; };
struct C : public A::B {};
struct D : public C::B {};
If this is standard conforming C++, what are reasonable applications for this construct?
Thanks.
Yes, it's valid C++. A class in its own scope (so both B and B::B refer to the same class B), and a class's parent class is in its own scope. So since B is in C's scope and B is in its own scope, C::B refers to B which is A::B.
(Side note: do not confuse a namespace with a scope.)
C++03 §9 paragraph 2 says:
A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.
The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name.
This is standard conforming C++.
A reasonable application of nested classes (through scope resolution) is the pImpl design pattern (though you can implement it in a way that will not demonstrate nested classes, but here I choose to demonstrate nested classes).
Note: Inheritance is one of the facets that can be confusing but the real concept is the scope resolution of a nested class.
//ExposedClass in Exposed.h
class CExposedClass
{
public:
CExposedClass();
~CExposedClass();
void doThis();
void doThat();
private:
class CXImpl;
CXImpl *pImpl;
};
//ExposedClass Impl in Exposed.cpp
#include "Exposed.h"
class CExposedClass::CXImpl
{
int someData;
};
CExposedClass::CExposedClass():pImpl(new CXImpl()){}
CExposedClass::~CExposedClass(){delete pImpl;}
void CExposedClass::doThis(){}
void CExposedClass::doThat(){}
class defined within the scope of one class is addressed from another scope using scope resolution.