1

I would like to know how to solve this problem. I don’t understand what this question is asking me:

dynamic_cast<Y>(new X)
  • To Be legal?
  • To probably succeed?
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • 2
    What is this supposed to do? – Alok Save Dec 02 '12 at 12:06
  • It is asking you which combinations of types for `Y` and `X` make this code legal and which combinations of types for `Y` and `X` make it likely to succeed. For example, if `Y` is a base class of `X` and has a virtual destructor, ... – David Schwartz Dec 02 '12 at 12:07

3 Answers3

3

The question should be:

What can you say about the definitions of X and Y so that the following code is legal, and furthermore that the cast succeeds?

Then the answer is fairly straight-forward: X has to be a complete type for the new expression to be legal. Dynamic casts are valid for upcasting to a non-virtual base, so if Y is a pointer to a non-virtual base (possibly CV-qualified, and including a pointer to X itself), the cast is valid and succeeds.

Moreover, there are other valid uses of dynamic casts on polymorphic types (i.e. classes with virtual functions). If X is polymorphic, then Y may be void *, or Y may be a pointer to any other class in the inheritance hierarchy of X. However, the cast will only succeed if Y is a pointer to a base (however, this base may be virtual!).

(The reasoning for the present is simpler than for an arbitrary dynamic cast, since we already know the dynamic type of the castee. In general, dynamic casts can do far more complicated things.)

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • That's not true. If `Y` is a pointer to a base class of `X`, then `X` doesn't have to be polymorphic. And if `Y` is `void*`, the cast will succeed (but will only be legal if `X` is polymorphic). – James Kanze Dec 02 '12 at 12:35
  • @JamesKanze: Interesting. Let me double-check that. Good point about `void*`, I should really have thought of that. – Kerrek SB Dec 02 '12 at 12:37
  • @JamesKanze: Thanks, you're right. Now the answer is getting very long. I wonder if I should just delete it. Let me see if I can make it correct without too many words. – Kerrek SB Dec 02 '12 at 12:40
  • @KerrekSB The real answer is fairly long. C++ isn't a simple language. (We've also not considered the role of cv_qualifiers; e.g. `Y` could be `X const*`, for example. In this case, since the results of `new X` can't be cv qualified, I don't think they play a significant role, but if you want to be complete...) – James Kanze Dec 02 '12 at 12:44
  • @JamesKanze: Edited -- what do you think? – Kerrek SB Dec 02 '12 at 12:44
  • @KerrekSB And your answer is still incorrect. _If_ `Y` is a pointer to `X`, or to a base class of `X`, then there is no requirement that `X` be polymorphic. In such cases, `dynamic_cast` is just another spelling of `static_cast`. – James Kanze Dec 02 '12 at 12:45
  • @JamesKanze: Yes, very true... can dynamic casts cast away constness, or only add it? Again the present case is simple because we know the value of the castee, and "a pointer" subsumes "a cv-qualified pointer". – Kerrek SB Dec 02 '12 at 12:46
  • @JamesKanze: I consider `X` to be a base class of itself. Does that make sense? I think that's what `is_base_of` says, too. – Kerrek SB Dec 02 '12 at 12:46
  • @KerrekSB They can only increase cv-qualification (which also include `volatile`, in addition to `const`); they cannot reduce it. But as I said, in this case, the results of `new X` have no cv-qualifications, so any cv-qualifiers in `Y` would only increase cv-qualification, and so be legal. – James Kanze Dec 02 '12 at 12:48
  • @KerrekSB I tend to agree with you that `X` is a base class of `X`. I'm not sure that the standard agrees, or that it agrees everywhere, and I'm sure that a lot of readers wouldn't automatically consider it to be the case. – James Kanze Dec 02 '12 at 12:49
  • @JamesKanze: The standard says that `B` is a base of `const B`; see 20.9.6/3. – Kerrek SB Dec 02 '12 at 12:50
  • @KerrekSB And §10/2 says something different. It's not the first time the standard has been inconsistent in its terminology. – James Kanze Dec 02 '12 at 13:01
3

First, to be legal, Y must be a pointer type. So let's rewrite the question as dynamic_cast<Y cv_qualifiers*>( new X ). Having done this, it's legal if X is a complete class type, and if either X is a polymorphic type, or Y is the same type as X or is a base class of X.

It will succeed if Y is the same as X, or is a base class of X. Note that in these cases, dynamic_cast has the same behavior as static_cast, and in fact corresponds to an implicit conversion, so one would normally just write new X, without any cast. (There are a few special cases where the cast might be necessary, typically when passing the results to a void* parameter. In such cases, I would prefer static_cast, but the semantics of the two are exactly the same in this case.)

Finally, there is one special case (which will also succeed): if X is a polymorphic type, and Y is void cv_qualifiers *. In this case, the dynamic_cast does have different semantics than static_cast, although since the X* returned from new X will have the type “pointer to most derived type”, the actual effect will be identical (and again, the same as the implicit conversion).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • @KerrekSB Good point. That would be another case where you might want a `dynamic_cast`. – James Kanze Dec 02 '12 at 12:42
  • @BarnabasSzabolcs `Y` can't be a reference type here, because we're converting a pointer (the results of a `new` expression). `dynamic_cast` can convert pointers to pointers, or references to references, but not pointers to references or vice versa. – James Kanze Dec 02 '12 at 16:12
1

It's completely unanswerable without knowing Y and X. For example, if Y is int, then illegal. Else, if Y is a pointer to a polymorphic class, it might succeed, or it might not, but there's certainly nothing "probable" about it. Finally, this is a rather nasty memory leak.

Puppy
  • 144,682
  • 38
  • 256
  • 465