Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Access of base class' private base class: qualification required, why

Reply
Thread Tools

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

 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      09-03-2005
#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();
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      09-03-2005
Alf P. Steinbach wrote:
> #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


 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      09-03-2005
* Victor Bazarov:
> Alf P. Steinbach wrote:
> > #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.


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...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      09-03-2005
"Alf P. Steinbach" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)
> * Victor Bazarov:
>> Alf P. Steinbach wrote:
>>> #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.

>
> 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.


--
John Carson

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      09-03-2005
John Carson wrote:
> [...]
> 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


 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      09-03-2005
* Victor Bazarov:
> John Carson wrote:
> > [...]
> > 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.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      09-03-2005
"Victor Bazarov" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)
> John Carson wrote:
>> [...]
>> 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.


--
John Carson

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Replacing a private function an keeping access to private variables Gregor Kofler Javascript 6 06-27-2008 10:24 PM
private(true) || private :make_time, what does it do? why? Rie! Ruby 3 03-26-2008 12:40 PM
Why is define_method private? Plus,what's the point of private methods? Daniel Finnie Ruby 3 12-16-2006 10:09 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
RE: Why I use private variables (WAS: RE:"private" variablesa.k.a. name mangling?) Jeremy Bowers Python 3 01-24-2005 10:52 PM



Advertisments