Topic: Q: private inheritance and ambigious names


Author: Stefan Rupp <st.rupp@t-online.de>
Date: 2000/08/15
Raw View
Hi,

Bill Wade schrieb:
>     if(dynamic_cast<Something*>(pBase) != NULL)
>         DoSomethingBroken();
>
> Here the runtime behavior depends (in part) on the accessibility of both
> Base and Something within derived classes pointed at by pBase (5.2.7p8).

Sorry, but I don't understand what you are saying. Could you please
elaborate?

Doei,
     struppi

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bill Wade" <billwade@wt.net>
Date: 2000/08/16
Raw View
"Stefan Rupp" <st.rupp@t-online.de> wrote

> Bill Wade schrieb:
> >     if(dynamic_cast<Something*>(pBase) != NULL)
> >         DoSomethingBroken();
> >
> > Here the runtime behavior depends (in part) on the accessibility of both
> > Base and Something within derived classes pointed at by pBase (5.2.7p8).
>
> Sorry, but I don't understand what you are saying. Could you please
> elaborate?

Sure.  First a little background.  I was responding to James Dennett, who
wrote

> are _any_
> situations where changing private/protected to public breaks
> otherwise legal code?

The usual answer to JD's question is no, and the example given looks
something like:

int i;    // global
class base { int i; };
class derived: base
{
  void foo(){ i = 7; }
}

This code is illegal.  The 'i' in foo refers to base::i, and derived doesn't
have access to it.  Some people have argued that the code should be legal,
and the 'i' in foo would refer to ::i.  If that were the language rule you
could break (change the behaviour of) code by making b::i public.  This is
not a problem with the current language.  derived::foo isn't legal and is in
no danger of becoming broken.

Now on to the "unusual" example which gives a "yes" answer to JD's question.

struct Base { virtual ~Base(); };
struct Something { virtual ~Something(); };
class Derived: public Base, private Something{};
void foo()
{
  Derived d;
  Base* pBase = &d;
  if(dynamic_cast<Something*>(pBase) != NULL)
    DoSomethingBroken();
}

This code is legal (mod typos, assuming a suitable declaration for
DoSomethingBroken).  It would also be legal if Something were a public base
of Derived.  However changing "private" to "public" changes the behavior of
the program.  Under most conditions dynamic cast can't "find" a base class
which isn't a public base of Derived.  If Something is private, the dynamic
cast fails (returns a null pointer, however the program is still legal).  If
Something is changed to be a public base of Derived the dynamic cast
succeeds, changing (breaking in this case) the behavior of the legal
program.

HTH



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Dennett <james@sessami.com>
Date: 2000/08/16
Raw View
--------------6394D767C87B57E69F915C8A
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Bill Wade wrote:

> "James Dennett" <james@jamesd.demon.co.uk> wrote
>
> > Maybe one of our resident gurus can tell us whether there are _any_
> > situations where changing private/protected to public breaks otherwise
> legal
> > code?
>
> You can make contrived examples
>
>    if(dynamic_cast<Base*>(pDerived) != NULL)
>        DoSomethingBroken();

Thankyou for that example, which shows me that my question was not quite the one I meant to ask.  I'm not sure quite how to phrase the question I really wanted to ask, but it's something more like: Can we find any code where changing private/protected to
public requires a translation-time diagnostic?  In other words, code where

if (false) {
  // mystery code here
}

compiles, but fails to compile when we change private/protected to public?  I'm hoping that the answer is no, because the only effect of access control _at translation time_ is to check whether otherwise legal constructs are disallowed because of access
restrictions.  Ideally, I'd like a reference into the Standard to back up any assertions, but any clues in the right direction would be appreciated.

A related question would be whether the private/protected to public transformation can have any defined effect on runtime behaviour except through dynamic_cast.

-- James Dennett <jdennett@acm.org>

--
Sessami is a trademark of Escape Velocity Technology Mobile Services Limited.
All information contained in this e-mail is confidential and for the use of
the addressee only.  If you receive this message in error please notify.



--------------6394D767C87B57E69F915C8A
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
Bill Wade wrote:
<blockquote TYPE=CITE>"James Dennett" &lt;james@jamesd.demon.co.uk> wrote
<p>> Maybe one of our resident gurus can tell us whether there are _any_
<br>> situations where changing private/protected to public breaks otherwise
<br>legal
<br>> code?
<p>You can make contrived examples
<p>&nbsp;&nbsp; if(dynamic_cast&lt;Base*>(pDerived) != NULL)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DoSomethingBroken();</blockquote>
Thankyou for that example, which shows me that my question was not quite
the one I&nbsp;meant to ask.&nbsp; I'm not sure quite how to phrase the
question I&nbsp;really wanted to ask, but it's something more like: Can
we find any code where changing private/protected to public requires a
translation-time diagnostic?&nbsp; In other words, code where
<p>if (false) {
<br>&nbsp; // mystery code here
<br>}
<p>compiles, but fails to compile when we change private/protected to public?&nbsp;
I'm hoping that the answer is no, because the only effect of access control
_at translation time_ is to check whether otherwise legal constructs are
disallowed because of access restrictions.&nbsp; Ideally, I'd like a reference
into the Standard to back up any assertions, but any clues in the right
direction would be appreciated.
<p>A related question would be whether the private/protected to public
transformation can have any defined effect on runtime behaviour except
through dynamic_cast.
<p>-- James Dennett &lt;jdennett@acm.org>
<pre>--&nbsp;
Sessami is a trademark of Escape Velocity Technology Mobile Services Limited.
All information contained in this e-mail is confidential and for the use of
the addressee only.&nbsp; If you receive this message in error please notify.</pre>
&nbsp;</html>

--------------6394D767C87B57E69F915C8A--

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: brangdon@cix.compulink.co.uk
Date: 2000/08/17
Raw View
In article <8mq3vp$14m$1@news.online.de>, sebmol@gmx.net (Sebastian
Moleski) wrote:
> If you want to find out about the rationale behind this design
> decision, have a look at the ARM, Chapter 11, first and second
> section.

See also D&E $2.10, which was published after the ARM and which makes it
seem less clear-cut. Stroustrup writes:

   I do wonder if this aspect of the C++ definition is the result
   of a genuine design decision. It could simply be a default
   outcome of the preprocessor technology used to implement
   C with Classes that didn't get reviewed when C++ was implemented
   with more appropriate compiler technology.

(In my view it is a bad rule, because it makes "private" less private.)

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bill Wade" <bill.wade@stoner.com>
Date: 2000/08/18
Raw View
"James Dennett" <james@jamesd.demon.co.uk> wrote

> Can we find any code where changing private/protected to public requires a
> translation-time diagnostic?

I don't believe so.  It certainly looks like the intent and wording of the
standard is that a compile-time construct that is invalid without
consideration of access control cannot become valid once access control is
considered.

I'm pretty sure you can make an example that gives you a compile time error
with the preprocessor, but that is a bit outside the box:

  #define foo x##private
  int foo;
  float xpublic;

Changing private to public causes a compile time error.  Although it isn't
legal to redefine a keyword, I think it is legal to paste onto a keyword as
shown.

> I'm hoping that the answer is no, because the only effect of access
control _at translation
> time_ is to check whether otherwise legal constructs are disallowed
because of access
> restrictions.  Ideally, I'd like a reference into the Standard to back up
any assertions

I read the last two sentences fo 11p4 (not 11.4) as backing up your
assertion.

> A related question would be whether the private/protected to public
transformation can
> have any defined effect on runtime behavior except through dynamic_cast.

I believe that changing access from private to public can change runtime
behavior from "unspecified" to "defined" by changing a non-POD class to a
POD class.

struct bar
{
  bool test(){ return ((char*)this) == &c; }
private:
  char c;
};

If you change private to public then bar is POD, and the rules (9.2p17)
require test() to return true.  As long as bar is not a POD (which is the
case as written), nothing in the standard requires test() to return true.

Does anyone know of existing compilers that actually re-order public/private
sections of a class for space or access optimizations?



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stefan Rupp <st.rupp@t-online.de>
Date: 2000/08/11
Raw View
Hi!

Bill Wade schrieb:
>    if(dynamic_cast<Base*>(pDerived) != NULL)
>        DoSomethingBroken();

At lest g++ 2.95.2 rejects this, if Base is a private base class
of Derived.

Doei,
     struppi

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bill Wade" <bill.wade@stoner.com>
Date: 2000/08/11
Raw View
"Stefan Rupp" <st.rupp@t-online.de> wrote in message
news:39943418.D1E51CE2@t-online.de...
> Hi!
>
> Bill Wade schrieb:
> >    if(dynamic_cast<Base*>(pDerived) != NULL)
> >        DoSomethingBroken();
>
> At lest g++ 2.95.2 rejects this, if Base is a private base class
> of Derived.

You and g++ are correct.  My example violates a "shall" (5.2.7p5).  Change
my example to

    if(dynamic_cast<Something*>(pBase) != NULL)
        DoSomethingBroken();

Here the runtime behavior depends (in part) on the accessibility of both
Base and Something within derived classes pointed at by pBase (5.2.7p8).



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stefan Rupp <st.rupp@t-online.de>
Date: 2000/08/09
Raw View
Barry Margolin schrieb:
> Accessibility is only checked *after* a name is resolved to a specific
> class.

Why?

Regards,
        Stefan

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bill Wade" <billwade@wt.net>
Date: 2000/08/10
Raw View
"James Dennett" <james@jamesd.demon.co.uk> wrote

> Maybe one of our resident gurus can tell us whether there are _any_
> situations where changing private/protected to public breaks otherwise
legal
> code?

You can make contrived examples

   if(dynamic_cast<Base*>(pDerived) != NULL)
       DoSomethingBroken();



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Dennett <james@jamesd.demon.co.uk>
Date: 2000/08/08
Raw View
Stefan Rupp wrote:

> struct A {
>   void foo();
> };
>
> struct A1 : private A {
> };
>
> struct B {
> };
>
> struct B1 : public B {
> };
>
> struct C : public A1, public B1 {
>   void bar() { foo(); } // ERROR: ambigious
> };
>
> Why is the call to foo() from within C ambigious? Only one foo()
> method - B1::B::foo() - may be called, because the other one is
> not accessible from within the context of C, since A1 is derived
> private from A.
>
> Is this just a bug in the GCC (2.95.2) implementation or is this
> behaviour conforming to the ISO standard?  I, certainly, don't
> like it at all! :-/
>

Name lookup comes before access is checked.  If you want to check for
ambiguity, you can mentally replace all occurrences of "private" and
"protected" with "public" -- if your code is ambiguous, changing public back
to private won't help you.  I believe that gcc does the right thing here.

Maybe one of our resident gurus can tell us whether there are _any_
situations where changing private/protected to public breaks otherwise legal
code?

-- James Dennett <jdennett@acm.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: llewelly.@@edevnull.dot.com
Date: 2000/08/08
Raw View
Stefan Rupp <st.rupp@t-online.de> writes:

> Good evening,
>
> please take a look at the following piece of code:
>
> struct A {
>   void foo();
> };
>
> struct A1 : private A {
> };

private inheritance means that nothing in A is accessible to classes
  (like C) derived from A1 .

>
> struct B {
> };
>
> struct B1 : public B {
> };
>
> struct C : public A1, public B1 {
>   void bar() { foo(); } // ERROR: ambigious
> };
>
> Why is the call to foo() from within C ambigious? Only one foo()
> method - B1::B::foo() - may be called, because the other one is
> not accessible from within the context of C, since A1 is derived
> private from A.
>
> Is this just a bug in the GCC (2.95.2) implementation or is this
> behaviour conforming to the ISO standard?  I, certainly, don't
> like it at all! :-/
>

Actually, gcc says that foo() is inaccessible -- *not*
  ambigous. (Note: the actual text of a diagnostic is entirely a
  QoI issume.)

{~/cc_exer}gcc -v
Reading specs from /usr/lib/gcc-lib/i686-pc-linux-gnu/2.95.2/specs
gcc version 2.95.2 19991024 (release)
{~/cc_exer}g++ -g -Wall private_mi.cc
private_mi.cc: In method `void C::bar()':
private_mi.cc:2: `void A::foo()' is inaccessible
private_mi.cc:15: within this context

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/08/08
Raw View
In article <398F1D16.65821DAB@t-online.de>, Stefan Rupp <st.rupp@t-
online.de> writes
>Why is the call to foo() from within C ambigious? Only one foo()
>method - B1::B::foo() - may be called, because the other one is
>not accessible from within the context of C, since A1 is derived
>private from A.

Access constraints do not hide names, only prevent their use if they are
eventually selected as a best match. IOWs access is not checked until
the selection has been made.


Francis Glassborow      Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stefan Rupp <st.rupp@t-online.de>
Date: 2000/08/09
Raw View
Good afternoon,

Stefan Rupp schrieb:
> struct A {
>   void foo();
> };
>
> struct A1 : private A {
> };
>
> struct B {
> };
>
> struct B1 : public B {
> };
>
> struct C : public A1, public B1 {
>   void bar() { foo(); } // ERROR: ambigious
> };

Argh, sorry, I forgot something: struct B should have been declared
like this:

struct B {
  void foo();
};

Otherwise there wouldn't be any name clash.

Regards,
        Stefan

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Sebastian Moleski" <sebmol@gmx.net>
Date: 2000/08/09
Raw View
"James Dennett" <james@jamesd.demon.co.uk>:
| Stefan Rupp wrote:
...
| Maybe one of our resident gurus can tell us whether there are _any_
| situations where changing private/protected to public breaks otherwise legal
| code?

Nowhere. It is not supposed to. If you want to find out about the rationale
behind this design decision, have a look at the ARM, Chapter 11, first and
second section. Although the ARM is not a standard, it explains some design
decisions in C++ made throughout the years quite well.

--
Sebastian Moleski
SurakWare Corp.
www.surakware.com (IE5 required)


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stefan Rupp <st.rupp@t-online.de>
Date: 2000/08/07
Raw View
Good evening,

please take a look at the following piece of code:

struct A {
  void foo();
};

struct A1 : private A {
};

struct B {
};

struct B1 : public B {
};

struct C : public A1, public B1 {
  void bar() { foo(); } // ERROR: ambigious
};

Why is the call to foo() from within C ambigious? Only one foo()
method - B1::B::foo() - may be called, because the other one is
not accessible from within the context of C, since A1 is derived
private from A.

Is this just a bug in the GCC (2.95.2) implementation or is this
behaviour conforming to the ISO standard?  I, certainly, don't
like it at all! :-/

Regards,
        struppi

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Barry Margolin <barmar@genuity.net>
Date: 2000/08/07
Raw View
In article <398F1D16.65821DAB@t-online.de>,
Stefan Rupp  <st.rupp@t-online.de> wrote:
>Why is the call to foo() from within C ambigious? Only one foo()
>method - B1::B::foo() - may be called, because the other one is
>not accessible from within the context of C, since A1 is derived
>private from A.

Accessibility is only checked *after* a name is resolved to a specific
class.

--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]