2

I once asked a question about how to design a piece of C++ code (which can be found here C++ - Good or bad practice?) and people told me that down-casting is considered a bad practice except for very specific scenarios.

However, I've seen many pieces of code in C# and Java where it seems to be a totally natural way of doing things. For example in Android SDK, you have the function Activity#findViewById() that returns a View that you then down cast to its actual class:

TextView tv = (TextView) this.findViewById( R.id.myTextView );

Why would this need to be avoided in C++ and not in other languages ?
I know that C# and Java both support introspection natively, and not C++ which would require on kind of type field, but in the end it's the same thing, isn't it ?

almightyGOSU
  • 3,731
  • 6
  • 31
  • 41
Virus721
  • 8,061
  • 12
  • 67
  • 123
  • Why would some random hater want to close this prefectly legit question ? – Virus721 Jun 08 '15 at 08:44
  • 4
    What makes you think that in other languages downcasting is fine? This question appears to start from an unsupported premise. – chi Jun 08 '15 at 08:47
  • @chi: I see where the OP is coming from. It is quite true that I have seen people warn against downcasting in C++ all the time, but quite rarely in other languages. – user541686 Jun 08 '15 at 08:48
  • @chi I assumed that the people who created android are not beginners and know what is a good or a bad practice and deduced from the way they designed their API that it was legit in Java. – Virus721 Jun 08 '15 at 08:49
  • @Virus721 how you can say down-casting is not bed practice in java ? if you are saying is right than why java has generic framework .... (i know java only from "another language" you have mentioned in your question) – Keval Jun 08 '15 at 08:54
  • C++ is a complex language with a lot of tools that solve specific problems. In your original question you used a wrong tool for the job, which is very common with downcasting. That is why it's shunned. There are perfectly valid applications of downcasting which are widely used (GUI frameworks, for example), but your specific case was not. – tsuki Jun 08 '15 at 09:08
  • @tsuki: It'd be nice if you could explain a bit why GUI frameworks require downcasting, I hadn't noticed that before. – user541686 Jun 08 '15 at 09:13
  • By the way, this is a question I had for a long time myself, and it took me a while to understand the answer to -- so I think you asked a good question! – user541686 Jun 08 '15 at 09:18
  • @Mehrdad You pass your widget to a GUI framework, it gets upcasted. User clicks it, callback is invoked, you get the widget as its base. You need to downcast it in order to use it. In general - downcasting is common when an object needs to pass through a framework and come out at the other end to perform its specific functionality. – tsuki Jun 08 '15 at 09:32
  • @tsuki: But then the object itself isn't the one that is performing its functionality, is it? Otherwise it could just have a virtual method for that task, and no need to cast... – user541686 Jun 08 '15 at 10:08
  • @Mehrdad To be precise - the object provides the functionality, but the logic and its context is not a part of its interface. – tsuki Jun 08 '15 at 10:10

3 Answers3

3

There are at least a couple of very different reasons, all of which are important:

  1. Conceptual: Other languages (especially Java, but to a large extent also C# and similar languages that strongly encourage the use of "reference types") use run-time polymorphism as a single tool to solve a lot of different problems (compile-time polymorphism, code reuse, performance enhancement, type erasure, run-time polymorphism, etc.), whereas C++ has different, more specialized and more appropriate solutions to the individual problems. (Templates, value types, and the like can be used to solve the individual problems.) Consequently, polymorphism in C++ is much less common in other languages, and in the remaining cases where it is common, it is often (but not always) inappropriate to use the equivalent of downcasts or instanceof.

  2. Pragmatic: The downcasting operator in C++ is fundamentally extraordinarily slow compared to the performance of other operators, in main part due to the fact that C++ allows multiple- and virtual-inheritance. Other languages don't, so their casts are much simpler. Moreover, certain compilers' implementations themselves have historically had even slower implementations of downcasting (e.g. I believe 64-bit Visual C++ was one of them). Consequently, developers try to avoid it at all costs due to its practical performance characteristics, on top of the conceptual reasons (#1).

Because of these reasons, it's really a bad idea to use dynamic_cast in C++ unless you absolutely need to.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • 2
    A downcast using `static_cast` is not "extraordinarily slow". – T.C. Jun 08 '15 at 09:03
  • Thanks for your answer. I don't understand this part though : `polymorphism in C++ is much less common in other languages`. Are you saying that, in C++, polymorphism should be used more often than in other languages ? – Virus721 Jun 08 '15 at 09:04
  • 3
    @T.C.: ...I *know* you know I'm talking about `dynamic_cast` and not `static_cast`. -__- – user541686 Jun 08 '15 at 09:04
  • 1
    @Virus721: I'm saying the opposite -- it should be used **less** often, because C++ has better solutions for many problems that other languages don't have better solutions for. – user541686 Jun 08 '15 at 09:05
0

The same idioms are used in C++, where an API takes a handler and passes a void* or long to it or stores such a variable with instances of API's objects. In WINAPI, RegisterClass is a typical example of the former, and Set/GetWindowLongPtr of the latter. These are the "very specific scenarios" you mentioned, and it applies to managed languages and C++ both.

Generally, statically typed languages shun downcasting, because it moves type checking from compile to run time.

Don Reba
  • 13,814
  • 3
  • 48
  • 61
-6

In other interpreter languages, type checking is done in interpreters such as JVM. In C++, you have to do type checking manually.

frogcdcn
  • 391
  • 1
  • 4
  • 14