Topic: Access specifiers for base classes
Author: daniels@biles.com (Brad Daniels)
Date: Fri, 18 Mar 1994 15:13:23 GMT Raw View
In article <CMtJGB.4p1@biles.com>, I wrote:
...
> I couldn't find any text to support either approach
>being right, but then, I'm notoriously bad at finding things like that in
>the standard.
Before someone beats me up, I'd like to say that the above was a slip of the
tongue. I meant to say either "the working document" or "any standard" (I
have the same rproblem with the C standard sometimes), not "the standard."
I am, of course, aware that there is not even a draft standard, let alone
an actual one.
- Brad
------------------------------------------------------------------------
+ Brad Daniels | "Let others praise ancient times; +
+ Biles and Associates | I am glad I was born in these." +
+ These are my views, not B&A's | - Ovid (43 B.C. - 17 A.D.) +
------------------------------------------------------------------------
Author: jdp@polstra.com (John Polstra)
Date: 18 Mar 1994 10:40:29 -0800 Raw View
In article <CMtJGB.4p1@biles.com>, Brad Daniels <daniels@biles.com> wrote:
> In article <2m7fed$f7c@seattle.polstra.com>,
> John Polstra <jdp@polstra.com> wrote:
> >No, the cast is not legal. See the ARM, section 11.2. Near the end of
> >that section, it states:
> >
> > Members and friends of a class X can implicitly convert an X* to a
> ^^^^^^^^^^
> > pointer to a private immediate base class of X.
> > ^^^^^^^^^
>
> Note the use of the word "implicitly." The cast above is an explicit
> conversion ...
Good point. I think you've changed my mind. I haven't found anything
in the ARM that makes a crystal clear statement about this, though.
> ... If the cast were to some completely
> unrelated pointer type, the conversion would definitely be legal, though the
> results of using such a pointer would be implementation defined. Since the
> cast is to a pointer to a base class, though, I'm not sure what's right.
Well, as programming travesties go, it's certainly no worse than casting
to a completely unrelated pointer type. So I would think that a quality
implementation should let it be legal, and should adjust the pointer if
necessary so that it really does point to the base class object, even
though it is private. I.e., the compiler should do its best to make
this lousy code work. I say this *only* because it's already legal to
cast to a completely unrelated pointer type anyway.
Really, though, the best advice is: Just don't do casts like that.
Just DON'T. There are all kinds of ways for a programmer to shoot
himself in the foot using C++, if that's what he's determined to do.
This is just one of them. The nice thing about the language is that,
*if* you use it properly, you are protected from a lot of potential
errors. The designers of the language have made it clear from day one
that the type checking features of the language are only designed to
help protect the programmer from accidental mistakes, not from
intentional suicide.
--
John Polstra jdp@polstra.com
John D. Polstra & Co., Inc. Phone (206) 932-6482
Seattle, Washington USA Fax (206) 935-1262
"Self-knowledge is always bad news." -- John Barth
Author: ah657@FreeNet.Carleton.CA (Michael Whiten)
Date: Sat, 19 Mar 1994 22:41:30 GMT Raw View
In a previous article, strassma@klavier.informatik.uni-stuttgart.de (Markus Strasser) says:
>Hello
>
>can anyone explain me the sense of access specifiers for base classes considering
>the following code:
>
> [ code deleted ...]
I would be out of my league to explain the "sense" of these specifiers, but
section 11.2 of the ARM gives a similar example which says that the above
call to why() is illegal as long as you rely on a (non-existant) implicit
conversion (i.e. no such conversion exists).
I have yet to see anything that specifically disallows an explicit cast
to an inaccessible base class though. It seems to me that this is
compiler dependent and frankly somewhat nonsensical. Private derived
classes can barely be described as a form of inheritence. It is much
closer to containment and hence the implicit conversion is illegal.
I don't think we add anything to C language compatibility by allowing
explicit conversions to an inaccessible base class. I think it should
be made a compile time error (or at least serious warning).
- Mike
--
Author: shepherd@debussy.sbi.com (Marc Shepherd)
Date: Mon, 21 Mar 1994 19:46:46 GMT Raw View
In article MpA@freenet.carleton.ca, ah657@FreeNet.Carleton.CA (Michael Whiten) writes:
>I have yet to see anything that specifically disallows an explicit cast
>to an inaccessible base class though. It seems to me that this is
>compiler dependent and frankly somewhat nonsensical. Private derived
>classes can barely be described as a form of inheritence. It is much
>closer to containment and hence the implicit conversion is illegal.
Yes, it is nonsensical. I don't agree that "private inheritance is much
closer to containment," because both inheritance AND containment can be
either public or private.
I believe that the ANSI C++ committee intends to make casting to a private
base class illegal, even though some compilers currently allow it.
Marc Shepherd
mshepherd@mhfl.sbi.com
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 23 Mar 94 17:50:49 GMT Raw View
Marc Shepherd (mshepherd@mhfl.sbi.com) writes
> I believe that the ANSI C++ committee intends to make casting to a private
> base class illegal, even though some compilers currently allow it.
The committee decided not to touch old-style casts, e.g. (T)e. These will work
as ever (for good and bad). The new-style casts, e.g. static_cast<T>(e), respect
privacy.
Just don't use old-style casts when you have a choice.
- Bjarne
PS Yes, I wanted to deprecate old-style casts, but that wasn't feasible.
Author: strassma@klavier.informatik.uni-stuttgart.de (Markus Strasser)
Date: Wed, 16 Mar 1994 09:06:32 GMT Raw View
Hello
can anyone explain me the sense of access specifiers for base classes considering
the following code:
#include <iostream.h>
class A{
public:
void test(){
cout << "A::test " << endl;
}
};
class B : private A{
};
class C : public B{
public:
void why(){
// test(); illegal
((A *)this)->test(); // legal !?!?!??
}
};
main(){
C c;
c.why();
}
Regards, Markus
Author: daniels@biles.com (Brad Daniels)
Date: Thu, 17 Mar 1994 17:04:58 GMT Raw View
In article <2m7fed$f7c@seattle.polstra.com>,
John Polstra <jdp@polstra.com> wrote:
>In article <CMr2Mw.J56@news.informatik.uni-stuttgart.de>,
>Markus Strasser <strassma@klavier.informatik.uni-stuttgart.de> wrote:
>> class A{
>> public:
>> void test(){
>> cout << "A::test " << endl;
>> }
>> };
>>
>>
>> class B : private A{
>> };
>>
>> class C : public B{
>> public:
>> void why(){
>> // test(); illegal
>> ((A *)this)->test(); // legal !?!?!??
>> }
>>
>> };
>
>No, the cast is not legal. See the ARM, section 11.2. Near the end of
>that section, it states:
>
> Members and friends of a class X can implicitly convert an X* to a
^^^^^^^^^^
> pointer to a private immediate base class of X.
> ^^^^^^^^^
Note the use of the word "implicitly." The cast above is an explicit
conversion, I'm not sure whether it's legal, since explicit pointer casts
generally circumvent the type system. If the cast were to some completely
unrelated pointer type, the conversion would definitely be legal, though the
results of using such a pointer would be implementation defined. Since the
cast is to a pointer to a base class, though, I'm not sure what's right.
DEC C++ says it's not legal because of the private inheritance, but g++,
as you mentioned, disagrees, as does HP C++ (which is based on Cfront).
DEC C++'s interpretation makes sense in the context of pointer magic
with multiple inheritance, while the other approach makes more sense in
the traditional C casting context. With a little experimentation I found
that both g++ and HP C++/Cfront do the proper pointer munging if B privately
inherits from multiple classes, which is inconsistent with the whole concept
of private inheritance. I couldn't find any text to support either approach
being right, but then, I'm notoriously bad at finding things like that in
the standard.
- Brad
------------------------------------------------------------------------
+ Brad Daniels | "Let others praise ancient times; +
+ Biles and Associates | I am glad I was born in these." +
+ These are my views, not B&A's | - Ovid (43 B.C. - 17 A.D.) +
------------------------------------------------------------------------
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Thu, 17 Mar 1994 23:56:24 GMT Raw View
In article <CMtJGB.4p1@biles.com> daniels@biles.com (Brad Daniels) writes:
>In article <2m7fed$f7c@seattle.polstra.com>,
>John Polstra <jdp@polstra.com> wrote:
>>In article <CMr2Mw.J56@news.informatik.uni-stuttgart.de>,
>>Markus Strasser <strassma@klavier.informatik.uni-stuttgart.de> wrote:
>>> class A{
>>> public:
>>> void test(){
>>> cout << "A::test " << endl;
>>> }
>>> };
>>>
>>>
>>> class B : private A{
>>> };
>>>
>>> class C : public B{
>>> public:
>>> void why(){
>>> // test(); illegal
>>> ((A *)this)->test(); // legal !?!?!??
>>> }
>>>
>>> };
>>
>>No, the cast is not legal. See the ARM, section 11.2. Near the end of
>>that section, it states:
>>
>> Members and friends of a class X can implicitly convert an X* to a
> ^^^^^^^^^^
>> pointer to a private immediate base class of X.
>> ^^^^^^^^^
>
>Note the use of the word "implicitly." The cast above is an explicit
>conversion, I'm not sure whether it's legal, since explicit pointer casts
>generally circumvent the type system. If the cast were to some completely
>unrelated pointer type, the conversion would definitely be legal, though the
>results of using such a pointer would be implementation defined. Since the
>cast is to a pointer to a base class, though, I'm not sure what's right.
>DEC C++ says it's not legal because of the private inheritance, but g++,
>as you mentioned, disagrees, as does HP C++ (which is based on Cfront).
>DEC C++'s interpretation makes sense in the context of pointer magic
>with multiple inheritance, while the other approach makes more sense in
>the traditional C casting context. With a little experimentation I found
>that both g++ and HP C++/Cfront do the proper pointer munging if B privately
>inherits from multiple classes, which is inconsistent with the whole concept
>of private inheritance. I couldn't find any text to support either approach
>being right, but then, I'm notoriously bad at finding things like that in
>the standard.
Yep. Too bad. Implementation dependent. I dont care.
This is an example of why we now have
reinterpret_cast<>()
static_cast<>()
A reinterpret cast to a publically known type always succeeds.
The static cast will do an upcast and fail if access is not granted.
The old style cast is ambiguous.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: strassma@posaune.informatik.uni-stuttgart.de (Markus Strasser)
Date: Fri, 18 Mar 1994 07:37:24 GMT Raw View
|> > class A{
|> > public:
|> > void test(){
|> > cout << "A::test " << endl;
|> > }
|> > };
|> >
|> >
|> > class B : private A{
|> > };
|> >
|> > class C : public B{
|> > public:
|> > void why(){
|> > // test(); illegal
|> > ((A *)this)->test(); // legal !?!?!??
|> > }
|> >
|> > };
|>
|> No, the cast is not legal. See the ARM, section 11.2. Near the end of
|> that section, it states:
|>
|> Members and friends of a class X can implicitly convert an X* to a
|> pointer to a private immediate base class of X.
Well, but the above cast is an explicit cast and no implicit conversion.... ?
Author: strassma@posaune.informatik.uni-stuttgart.de (Markus Strasser)
Date: Fri, 18 Mar 1994 08:40:18 GMT Raw View
|> >> class A{
|> >> public:
|> >> void test(){
|> >> cout << "A::test " << endl;
|> >> }
|> >> };
|> >>
|> >>
|> >> class B : private A{
|> >> };
|> >>
|> >> class C : public B{
|> >> public:
|> >> void why(){
|> >> // test(); illegal
|> >> ((A *)this)->test(); // legal !?!?!??
|> >> }
|> >>
|> >> };
|> >
|> >No, the cast is not legal. See the ARM, section 11.2. Near the end of
|> >that section, it states:
|> >
|> > Members and friends of a class X can implicitly convert an X* to a
|> ^^^^^^^^^^
|> > pointer to a private immediate base class of X.
|> > ^^^^^^^^^
|>
|> Note the use of the word "implicitly." The cast above is an explicit
|> conversion, I'm not sure whether it's legal, since explicit pointer casts
|> generally circumvent the type system. If the cast were to some completely
|> unrelated pointer type, the conversion would definitely be legal, though the
|> results of using such a pointer would be implementation defined. Since the
|> cast is to a pointer to a base class, though, I'm not sure what's right.
|> DEC C++ says it's not legal because of the private inheritance, but g++,
|> as you mentioned, disagrees, as does HP C++ (which is based on Cfront).
|> DEC C++'s interpretation makes sense in the context of pointer magic
|> with multiple inheritance, while the other approach makes more sense in
|> the traditional C casting context. With a little experimentation I found
|> that both g++ and HP C++/Cfront do the proper pointer munging if B privately
|> inherits from multiple classes, which is inconsistent with the whole concept
|> of private inheritance. I couldn't find any text to support either approach
|> being right, but then, I'm notoriously bad at finding things like that in
|> the standard.
I looked about this special case of pointer conversion in the ARM and found
nothing. Chapter 5 states that a pointer to one object type may be
explicitly converted to a pointer to another object type - the special case
that the other type is a private base class is not mentioned. The other point
was the above cited section in the ARM. That was all I found.
I experienced with the xlC and had to discover that xlC has a bug:
class A{
public:
int i;
A():i(5){}
void test(){ cout << "A::test " << i << endl;}
};
class B{
public:
int i;
B():i(10){}
void test(){ cout << "B::test " << i << endl;}
};
class C: private A , private B{
};
class D: public C{
public:
void test(){
((A*)this)->test(); // OK
((B*)this)->test(); // NOT ok :
// private member "B::test()" cannot be accessed.
}
};
Markus