468,774 Members | 2,655 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,774 developers. It's quick & easy.

Private inheritance renders class inaccessible

The following code does not compile:

class X {};

class Y : private X {};

class Z : public Y
{
public:
Z(X&) {} // problem here
};

Both GCC 3.3 and Comeau Online give the same error:

test.cpp: In constructor `Z::Z(X&)':
test.cpp:1: error: `class X' is inaccessible
test.cpp:8: error: within this context

I can fix the error by changing the broken ctor to Z(::X&) to
explicitly refer to the global class ::X, but I don't understand why I
have to. Can someone explain why private inheritance makes X
inaccessible in this situation?

Thanks.

Sep 23 '05 #1
7 2934
* sp**@grog.net:
The following code does not compile:

class X {};

class Y : private X {};

class Z : public Y
{
public:
Z(X&) {} // problem here
};

Both GCC 3.3 and Comeau Online give the same error:

test.cpp: In constructor `Z::Z(X&)':
test.cpp:1: error: `class X' is inaccessible
test.cpp:8: error: within this context

I can fix the error by changing the broken ctor to Z(::X&) to
explicitly refer to the global class ::X, but I don't understand why I
have to. Can someone explain why private inheritance makes X
inaccessible in this situation?


It's not obvious. But last time we rehashed this in this group (I posed the
question, just as mystified as you probably are) a natural explanation was
provided by Victor Bazarov, I think it was. Namely that the inheritance for Y
introduces the name X in the class, and ordinary access rules apply when
referring to X that way -- as a name in the class. Qualifying X,
essentially referring to it via another route, fixes that. I can sort of
understand how that results from the detailed technical rules, but I think
that if that explanation is correct, and nothing so far has indicated that it
could be incorrect, then it's a language design bug... ;-)

--
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?
Sep 23 '05 #2
sp**@grog.net wrote:
The following code does not compile:

class X {};

class Y : private X {};

class Z : public Y
{
public:
Z(X&) {} // problem here
};

Both GCC 3.3 and Comeau Online give the same error:

test.cpp: In constructor `Z::Z(X&)':
test.cpp:1: error: `class X' is inaccessible
test.cpp:8: error: within this context

I can fix the error by changing the broken ctor to Z(::X&) to
explicitly refer to the global class ::X, but I don't understand why I
have to. Can someone explain why private inheritance makes X
inaccessible in this situation?


The name 'X' (without qualification) is inserted into class X's scope when
you define it. That name becomes a member for the purposes of name
lookup. In 'Y' that member is _inherited_, but made *private*. In 'Z' it
is inherited again, but is inaccessible.

Now, when you qualify the name (by means of the name resolution operator,
colon-colon), you issue an explicit instruction to your compiler as to
which 'X' out of two (one in the global scope and the other in the class
scope) to choose. Since the global one is accessible, you have no problem
like with the member. According to name lookup rules, however, the member
is preferred when an unqualified name is used.

V
Sep 23 '05 #3
Alf P. Steinbach wrote:
[...] Namely that the inheritance for Y
introduces the name X in the class,
Actually 'X' has its own name as a member, 'Y' just inherits it.
Relevant clause is 9, paragraph 2.
[..]


V
Sep 23 '05 #4
Thanks Victor. I won't pretend this is obvious, but I the reasoning
makes sense.

Sep 23 '05 #5
Victor Bazarov wrote:
sp**@grog.net wrote:
The following code does not compile:

class X {};

class Y : private X {};

class Z : public Y
{
public:
Z(X&) {} // problem here
};

Both GCC 3.3 and Comeau Online give the same error:

test.cpp: In constructor `Z::Z(X&)':
test.cpp:1: error: `class X' is inaccessible
test.cpp:8: error: within this context

I can fix the error by changing the broken ctor to Z(::X&) to
explicitly refer to the global class ::X, but I don't understand why I
have to. Can someone explain why private inheritance makes X
inaccessible in this situation?

The name 'X' (without qualification) is inserted into class X's scope when
you define it. That name becomes a member for the purposes of name
lookup. In 'Y' that member is _inherited_, but made *private*. In 'Z' it
is inherited again, but is inaccessible.

Now, when you qualify the name (by means of the name resolution operator,
colon-colon), you issue an explicit instruction to your compiler as to
which 'X' out of two (one in the global scope and the other in the class
scope) to choose. Since the global one is accessible, you have no problem
like with the member. According to name lookup rules, however, the member
is preferred when an unqualified name is used.

V


Am I way off the mark in thinking that is similar in spirit to the
situation where, for example, defining a function foo() in a derived
class hides not only foo() in the base class but any other overloaded
versions of foo (say, foo(int)) in the base class too?

It seems that C++ is at least consistent here, in that it stops looking
for a name as soon as it finds it in any scope, even if the found
instance is not appropriate/useful/sensible.

As to motivation (which someone else brought up elsewhere in this
thread), I've seen it argued that this is sensible behavior in the case
of function overloading as it prevents a deeply derived class from
accidentally invoking a function about whose existence it is perhaps
unaware. Can the same argument be made in this case?

Mark
Sep 24 '05 #6
Mark P wrote:
[...]
Am I way off the mark in thinking that is similar in spirit to the
situation where, for example, defining a function foo() in a derived
class hides not only foo() in the base class but any other overloaded
versions of foo (say, foo(int)) in the base class too?
Name hides another name. Arguments have nothing to do with it.
'foo' member function in a derived class would hide 'foo' data member
just as well.
It seems that C++ is at least consistent here, in that it stops
looking for a name as soon as it finds it in any scope, even if the
found instance is not appropriate/useful/sensible.
That is not always so. The rules aren't that simple, anyway.
As to motivation (which someone else brought up elsewhere in this
thread), I've seen it argued that this is sensible behavior in the
case of function overloading as it prevents a deeply derived class
from accidentally invoking a function about whose existence it is
perhaps unaware. Can the same argument be made in this case?


Generally speaking, you're correct. The big deal would be if the
meaning (or the behaviour) of the "other" X (or foo) changed, there
should be no effect on the class who defines its own. Now, whether
it applies here I am not sure, but straight-forwardness of name
lookup is probably important.

V
Sep 24 '05 #7
<sp**@grog.net> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com...
The following code does not compile:

class X {};

class Y : private X {};

class Z : public Y
{
public:
Z(X&) {} // problem here
};

Both GCC 3.3 and Comeau Online give the same error:

test.cpp: In constructor `Z::Z(X&)':
test.cpp:1: error: `class X' is inaccessible
test.cpp:8: error: within this context


By using private inheritance, you're telling the compiler you DON'T
want classes derived from Y to have access to their "X" part.

If you want to allow classes derived from Y to access their own
"X" part, you could use protected inheritance instead:

class X
{

};

class Y : protected X
{

};

class Z : public Y
{
public:
Z(X&) {}
};

int main()
{
return 0;
}

You'll find that compiles and runs without error.

--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant

Sep 24 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Dave Theese | last post: by
8 posts views Thread by Dave | last post: by
10 posts views Thread by Ioannis Vranos | last post: by
2 posts views Thread by MJ | last post: by
6 posts views Thread by Jonathan Potter | last post: by
8 posts views Thread by __PPS__ | last post: by
3 posts views Thread by bob | last post: by
4 posts views Thread by zhangyefei.yefei | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
2 posts views Thread by Marin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.