Topic: dynamic_cast and private inheritance
Author: bill@gibbons.org (Bill Gibbons)
Date: Fri, 20 Jun 2003 01:46:31 +0000 (UTC) Raw View
In article <3EEB205C.7040707@ieee.org>, jhyslop@ieee.org (Jim Hyslop)
wrote:
> Alexander Nasonov wrote:
> > If you are deriving from IntermediateN you are expecting that if TN (N=1,2)
> > is unambiguous base of IntermediateN then derived class can be
> > dynamic_cast'ed to TN regardless of how IntermediateN is derived from TN.
> > For public inheritance that's fine but for private one the second bullet in
> > 5.2.7/8 [expr.dynamic.cast] doesn't get you a chance to access T2.
>
> Don't expect to see this changed. The restriction to public base classes
> is deliberate.
Deliberate, but wrong. It clearly breaks encapsulation in a nontrivial
way.
I argued for fixing this in my paper
N0347 "Local Disambiguation of Dynamic Cross-Casts" (1993)
which proposed, basically, that if the cast would be valid in a local
subset of the hierarchy then it should remain valid in the complete
hierarchy.
Obviously anything else makes it impossible to use dynamic_cast in any
class that might be included in a larger hierarchy without placing
unnecessary restrictions on that derivation based on internal
implementation details of the class.
At the time this paper was written many J16/WG21 papers were not
archived in machine-readable form, including this one. However, I was
able to locate the original and have sent the PDF to the maintainer of
http://std.dkuug.dk/jtc1/sc22/wg21 with a request that it be added to the
archive.
-- Bill Gibbons
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alnsn-mycop@yandex.ru (Alexander Nasonov)
Date: Fri, 20 Jun 2003 19:36:21 +0000 (UTC) Raw View
Jim Hyslop wrote:
> Alexander Nasonov wrote:
>> If you are deriving from IntermediateN you are expecting that if TN
>> (N=1,2) is unambiguous base of IntermediateN then derived class can be
>> dynamic_cast'ed to TN regardless of how IntermediateN is derived from TN.
>> For public inheritance that's fine but for private one the second bullet
>> in 5.2.7/8 [expr.dynamic.cast] doesn't get you a chance to access T2.
>
> Don't expect to see this changed. The restriction to public base classes
> is deliberate. See
> http://www.cuj.com/documents/s=7979/cujcexp2009hyslop/ [footnote] for
> an explanation behind this restriction.
It's not surprising to me. The surprise is different strategy for two cases.
Let me quote 5.2.7 [expr.dynamic.cast] again:
> 8 The runtime check logically executes as follows:
> - If, in the most derived object pointed (referred) to by v, v points
> (refers) to a public base class subobject of a T object, and if only one
>object of type T is derived from the subobject pointed (referred) to by v,
> the result is a pointer (an lvalue referring) to that T object.
It looks like top-to-bottom search in the hierarchy. So, the algorithm
starts from a pointer to Base then goes to derived classes until it finds
T. Accessibility of T from the most derived object is not checked!
> - Otherwise, if v points (refers) to a public base class subobject of the
> most derived object, and the type of the most derived object has an
> unambiguous public base class of type T, the result is a pointer (an
lvalue
> referring) to the T subobject of the most derived object.
This algorithm starts from the most derived object and checks the
accesibility of T.
So, if you derived privately from IntermediateN (see my previous post) then
you can expect two different results although T is unambiguous base of the
most derived objects in both cases.
Another dark-side feature of C++?
--
Alexander Nasonov
Remove minus and all between minus and at from my e-mail for timely response
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jhyslop@ieee.org (Jim Hyslop)
Date: Sun, 15 Jun 2003 05:26:11 +0000 (UTC) Raw View
Alexander Nasonov wrote:
> If you are deriving from IntermediateN you are expecting that if TN (N=1,2)
> is unambiguous base of IntermediateN then derived class can be
> dynamic_cast'ed to TN regardless of how IntermediateN is derived from TN.
> For public inheritance that's fine but for private one the second bullet in
> 5.2.7/8 [expr.dynamic.cast] doesn't get you a chance to access T2.
Don't expect to see this changed. The restriction to public base classes
is deliberate. See
http://www.cuj.com/documents/s=7979/cujcexp2009hyslop/ [footnote] for
an explanation behind this restriction.
Note that at first glance this article may not appear to apply, but the
restrictions apply also to dynamic_cast.
FOOTNOTE: Please note that any URLs to articles in the CUJ Experts Forum
(www.cuj.com/experts) that you may have bookmarked are now invalid. The
CUJ webmaster decided it was OK to move all the articles around without
informing anyone.
--
Jim
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bop2@telia.com ("Bo Persson")
Date: Mon, 16 Jun 2003 19:39:20 +0000 (UTC) Raw View
"Jim Hyslop" <jhyslop@ieee.org> skrev i meddelandet
news:3EEB205C.7040707@ieee.org...
> FOOTNOTE: Please note that any URLs to articles in the CUJ Experts
Forum
> (www.cuj.com/experts) that you may have bookmarked are now invalid.
The
> CUJ webmaster decided it was OK to move all the articles around
without
> informing anyone.
Yes, all iterators are invalidated after a reallocation. :-)
Bo Persson
bop2@telia.com
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alnsn-mycop@yandex.ru (Alexander Nasonov)
Date: Thu, 5 Jun 2003 18:00:41 +0000 (UTC) Raw View
Output of this program is strange to me:
#include <iostream>
struct Base { virtual ~Base() {} };
struct T1 : Base {};
struct Intermediate1 : T1 {};
struct Derived1 : private Intermediate1
{
Base* base() { return this; }
};
struct T2 {};
struct Intermediate2 : Base, T2 {};
struct Derived2 : private Intermediate2
{
Base* base() { return this; }
};
int main()
{
Derived1 d1;
Derived2 d2;
std::cout << dynamic_cast<T1*>(d1.base()) << '\n';
std::cout << dynamic_cast<T2*>(d2.base()) << '\n';
}
g++ 3.2 output:
0xbffff950
0
If you are deriving from IntermediateN you are expecting that if TN (N=1,2)
is unambiguous base of IntermediateN then derived class can be
dynamic_cast'ed to TN regardless of how IntermediateN is derived from TN.
For public inheritance that's fine but for private one the second bullet in
5.2.7/8 [expr.dynamic.cast] doesn't get you a chance to access T2.
5.2.7 [expr.dynamic.cast]
--- quote ---
8 The runtime check logically executes as follows:
- If, in the most derived object pointed (referred) to by v, v points
(refers) to a public base class subobject of a T object, and if only one
object of type T is derived from the subobject pointed (referred) to by v,
the result is a pointer (an lvalue referring) to that T object.
- Otherwise, if v points (refers) to a public base class subobject of the
most derived object, and the type of the most derived object has an
unambiguous public base class of type T, the result is a pointer (an lvalue
referring) to the T subobject of the most derived object.
- Otherwise, the runtime check fails.
--- end of quote ---
It can be changed this way (note /**/ comment and <new> tag):
- Otherwise, if v points (refers) to a public base class subobject of the
most derived object, and the type of the most derived object has an
unambiguous /*public*/ base class of type T, <new> and exists a subobject
of most derived object derived publicly from T </new>, the result is a
pointer (an lvalue referring) to the T subobject of the most derived
object.
--
Alexander Nasonov
Remove minus and all between minus and at from my e-mail for timely response
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alnsn-mycop@yandex.ru (Alexander Nasonov)
Date: Fri, 6 Jun 2003 21:03:59 +0000 (UTC) Raw View
Alexander Nasonov wrote:
> It can be changed this way (note /**/ comment and <new> tag):
Actually, I've changed only a half.
An idea is to find intermediate subobject of a most derived object which is
publicly derived from T and from subobject pointed to (refered to) by v.
Public inheritance between this intermediate and the most derived object is
not required. And of cause T must be unambiguous base (not necessary
public) of the most derived object.
--
Alexander Nasonov
Remove minus and all between minus and at from my e-mail for timely response
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]