question on access privileges for containment of a class alsoprivately derived from

G

galathaea

after reviewing some code that was not compiling
i found the following simple program could reproduce the issue

-+-+-+-

class Base
{
private:
int data_;
};

// note the private inheritance
class Derived : Base
{
private:
};

class UltraDerived : public Derived
{
private:
Base aBaseAsMember_;
};

int main()
{
UltraDerived myUDerived;
}

-+-+-+-

gcc of various versions
(4.2.1 for instance)
responds "error: class Base is inaccessible"

msvs 2008 (9.0.30729.1 SP)
responds "error C2247: 'Base' not accessible because 'Derived' uses
'private' to inherit from 'Base'"

apparently the private inheritance hides access to the type name
even for an entirely unrelated attempt at containment

is there a technical reason this is not allowed?
i can't see that this would cause cyclic dependencies
(and cyclic dependencies isn't something the syntax tries to prevent
elsewhere)

or compiler bugs?

(the use of this kind of construct is pretty dubious
but it turned up in usage of a third party library
which had taken the unfortunate decision of the private inheritance
of a utility class that the derived needed another copy of)

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
galathaea: prankster, fablist, magician, liar
 
N

Noah Roberts

galathaea said:
after reviewing some code that was not compiling
i found the following simple program could reproduce the issue

-+-+-+-

class Base
{
private:
int data_;
};

// note the private inheritance
class Derived : Base
{
private:
};

class UltraDerived : public Derived
{
private:
Base aBaseAsMember_;

Change to:
::Base aBaseAsMember_;

It seems that the compiler, whether due to a bug or not, is thinking
that you are trying to refer to the super of Derived as part of some
sort of name resolution specification, not to the global type "Base".
 
G

galathaea

Name resolution is performed before access rights are considered.

ah!
you're right...

changing it to
::Base aBaseAsMember_;
works fine!

thanks

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
galathaea: prankster, fablist, magician, liar
 
G

galathaea

Change to:
     ::Base aBaseAsMember_;


It seems that the compiler, whether due to a bug or not, is thinking
that you are trying to refer to the super of Derived as part of some
sort of name resolution specification, not to the global type "Base".

thanks!

i found that out just as you were posting
from the hint on name resolution

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
galathaea: prankster, fablist, magician, liar
 
I

imuaplease

after reviewing some code that was not compiling
i found the following simple program could reproduce the issue

             -+-+-+-

class Base
{
private:
  int data_;

};

// note the private inheritance
class Derived : Base
{
private:

};

class UltraDerived : public Derived
{
private:
  Base aBaseAsMember_;

};

int main()
{
  UltraDerived myUDerived;

}

             -+-+-+-

gcc of various versions
  (4.2.1 for instance)
responds "error: class Base is inaccessible"

msvs 2008 (9.0.30729.1 SP)
responds "error C2247: 'Base' not accessible because 'Derived' uses
'private' to inherit from 'Base'"

apparently the private inheritance hides access to the type name
even for an entirely unrelated attempt at containment

is there a technical reason this is not allowed?
i can't see that this would cause cyclic dependencies
(and cyclic dependencies isn't something the syntax tries to prevent
elsewhere)

or compiler bugs?

(the use of this kind of construct is pretty dubious
 but it turned up in usage of a third party library
   which had taken the unfortunate decision of the private inheritance
   of a utility class that the derived needed another copy of)

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
galathaea: prankster, fablist, magician, liar

What exactly is the post all about, how can I link it to social
story ? I can't imagine your problem
 
J

James Kanze

Change to:
::Base aBaseAsMember_;
It seems that the compiler, whether due to a bug or not, is
thinking that you are trying to refer to the super of Derived
as part of some sort of name resolution specification, not to
the global type "Base".

It's an odd side effect of class name injection. For various
reasons (which I've forgotten, although they've been explained
to me several times), the name of a class is injected into that
class' scope. This means that things like:

class C { int C ; } ;

are illegal (since the name C is already present in the scope of
the class). In the case above, it means that name lookup (which
takes place before access control) of Base in UltraDerived will
find Base in Base, and not in the global namespace. And the
Base in Base is private.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top