Access of base class' private base class: qualification required, why

  • Thread starter Alf P. Steinbach
  • Start date
A

Alf P. Steinbach

#include <iostream>

struct Belcher
{
int x;
void belch() { std::cout << x << std::endl; }
Belcher( int anX ): x( anX ) {}
};

struct Person: private Belcher { Person(): Belcher( 666 ) {} };

struct Viking: Person
{
void eat() {}
void dine( bool belch )
{
eat();
if( belch )
{
Viking* pv = this;
::Belcher* p = :):Belcher*) pv;
// Why is qualification necessary here?
}
}
};

int main()
{
Viking v;
Viking* pv = &v;
Belcher* p = (Belcher*) pv;
p->belch();
}
 
V

Victor Bazarov

Alf said:
#include <iostream>

struct Belcher
{
int x;
void belch() { std::cout << x << std::endl; }
Belcher( int anX ): x( anX ) {}
};

struct Person: private Belcher { Person(): Belcher( 666 ) {} };

struct Viking: Person
{
void eat() {}
void dine( bool belch )
{
eat();
if( belch )
{
Viking* pv = this;
::Belcher* p = :):Belcher*) pv;
// Why is qualification necessary here?

By qualifying you explicitly specify to use the global name 'Belcher'
not the 'Belcher' name brought into the scope of this class from the
Person's scope -- the grandfather class. If you remember, a name in
scope _hides_ the name in the enclosing scope. 'Belcher' in 'Viking'
comes from 'Person' and in 'Person' it hides '::Belcher'.

I am a bit perplexed by the need to do that C-style cast. If the base
class is private, you're not supposed to use it. Why force the code
into doing something that is purposely not there?
}
}
};

int main()
{
Viking v;
Viking* pv = &v;
Belcher* p = (Belcher*) pv;
p->belch();
}

V
 
A

Alf P. Steinbach

* Victor Bazarov:
By qualifying you explicitly specify to use the global name 'Belcher'
not the 'Belcher' name brought into the scope of this class from the
Person's scope -- the grandfather class. If you remember, a name in
scope _hides_ the name in the enclosing scope.

Well, yes, but it isn't really in scope in Viking when it's private in
Person, is it? I mean, that's an implementation detail of Person. It
shouldn't affect Viking, except for virtual member functions.

'Belcher' in 'Viking'
comes from 'Person' and in 'Person' it hides '::Belcher'.

I am a bit perplexed by the need to do that C-style cast. If the base
class is private, you're not supposed to use it. Why force the code
into doing something that is purposely not there?

Just to do the C cast...
 
J

John Carson

Alf P. Steinbach said:
* Victor Bazarov:

Well, yes, but it isn't really in scope in Viking when it's private in
Person, is it? I mean, that's an implementation detail of Person. It
shouldn't affect Viking, except for virtual member functions.

By 10.2, name lookup takes place before access control. If I have
interpreted this correctly, this means that the fact that Belcher is private
in Person is irrelevant for name lookup purposes.

What surprises me is that inheriting from Belcher apparently has the effect
of declaring a Belcher type that is distinct from the Belcher type declared
at global scope. But I guess this makes sense; after all a base subobject
can be of zero size, whereas a free-standing object of the same-named class
cannot be of zero size.
 
V

Victor Bazarov

John said:
[...]
What surprises me is that inheriting from Belcher apparently has the
effect of declaring a Belcher type that is distinct from the Belcher
type declared at global scope.

Why does that surprise you?

3.4/3 says that the name of the class is a member of that class for
the purposes of name lookup. Since all members are inherited (unless
they are hidden), the name of any base class is considered a member
of the derived class. If you inherit the derived class again, the
member of it will become a member of the next derived class and so on.
But I guess this makes sense; after
all a base subobject can be of zero size, whereas a free-standing
object of the same-named class cannot be of zero size.

I am not sure how you stitch sizes into that... It's simpler.

class A {};

class B { // I purposely didn't inherit B from A
typedef A A; // that was happens if inherited; choose your
// access specifier. 'A' is now a member of 'B'
};

class C : B {
// A is a member here too
};

int main() {
A a; // OK
B::A ba; // cannot access private name
C::A ca; // same error
}

V
 
A

Alf P. Steinbach

* Victor Bazarov:
John said:
[...]
What surprises me is that inheriting from Belcher apparently has the
effect of declaring a Belcher type that is distinct from the Belcher
type declared at global scope.

Why does that surprise you?

3.4/3 says that the name of the class is a member of that class for
the purposes of name lookup. Since all members are inherited (unless
they are hidden), the name of any base class is considered a member
of the derived class. If you inherit the derived class again, the
member of it will become a member of the next derived class and so on.
But I guess this makes sense; after
all a base subobject can be of zero size, whereas a free-standing
object of the same-named class cannot be of zero size.

I am not sure how you stitch sizes into that... It's simpler.

class A {};

class B { // I purposely didn't inherit B from A
typedef A A; // that was happens if inherited; choose your
// access specifier. 'A' is now a member of 'B'
};

class C : B {
// A is a member here too
};

int main() {
A a; // OK
B::A ba; // cannot access private name
C::A ca; // same error
}

Thanks Victor, you cleared this up, and my frust-o-meter is now starting to
calm down. :)
 
J

John Carson

Victor Bazarov said:
John said:
[...]
What surprises me is that inheriting from Belcher apparently has the
effect of declaring a Belcher type that is distinct from the Belcher
type declared at global scope.

Why does that surprise you?

Sheer ignorance on my part Victor.
3.4/3 says that the name of the class is a member of that class for
the purposes of name lookup. Since all members are inherited (unless
they are hidden), the name of any base class is considered a member
of the derived class. If you inherit the derived class again, the
member of it will become a member of the next derived class and so on.

I hunted around for a section such as you cite, but couldn't find it. Thanks
for the info.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top