3

I was reading about dynamic_cast and then I encountered the following statement (from cplusplus.com):

Compatibility note: This type of dynamic_cast requires Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This needs to be enabled for runtime type checking using dynamic_cast to work properly with these types.

After the example:

// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;

class Base { virtual void dummy() {} };
class Derived: public Base { int a; };

int main () {
  try {
    Base * pba = new Derived;
    Base * pbb = new Base;
    Derived * pd;

    pd = dynamic_cast<Derived*>(pba);
    if (pd==0) cout << "Null pointer on first type-cast.\n";

    pd = dynamic_cast<Derived*>(pbb);
    if (pd==0) cout << "Null pointer on second type-cast.\n";

  } catch (exception& e) {cout << "Exception: " << e.what();}
  return 0;
}

What does the author mean by "this type of dynamic_cast"? Isn't dynamic_cast only used for polymorphic classes(almost)? And he mentions this RTTI as something that is needed for the dynamic cast to work, does that mean that you have to use dynamic_cast with caution because you do not know if it is supported fully by the compiler and therefore makes it riskier than the other casting operators which do not need this RTTI?

Sisir
  • 4,584
  • 4
  • 26
  • 37
  • 9
    You should take everything cplusplus.com says with a grain of salt. For example, I'm not aware of any C++ compiler that disables RTTI by default. –  Jun 08 '17 at 20:21
  • 5
    If you disable RTTI for C++ you either have a *very* good reason and *really* know what you are doing and have profiling to back up your claim that it matters. Or; you're an idiot. Btw, stop reading cplusplus.com and read cppreference.com and other good sources instead. – Jesper Juhl Jun 08 '17 at 20:28
  • @NeilButterworth I can imagine that a compiler for a very limited embedded system might consider RTTI to be too much overhead and leave it off by default, but I haven't worked in that domain for many years and haven't encountered any either. – Mark Ransom Jun 08 '17 at 20:29
  • this is close to being a duplicate of: https://stackoverflow.com/questions/2253168/dynamic-cast-and-static-cast-in-c and links from there – Dr t Jun 08 '17 at 20:31
  • Anyway, if you disable RTTI, e.g. by using -fno-rtti, I suppose you will get compiler errors when using dynamic casts (at least I get them). So I suppose it to be "save", as I think it will not compile with disabled RTTI. – Stephan Lechner Jun 08 '17 at 20:34
  • @NeilButterworth I googled and found https://github.com/android-ndk/ndk/issues/212 for example. – Mark Ransom Jun 08 '17 at 20:34
  • @Mark I think that's the build system not the compiler. –  Jun 08 '17 at 20:37
  • Possible duplicate of [dynamic\_cast with RTTI disabled](https://stackoverflow.com/questions/7687041/dynamic-cast-with-rtti-disabled) – Richard Critten Jun 08 '17 at 20:55

3 Answers3

3

The compatibility note relates to the immediately preceding paragraph (and code example):

But dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type.

And it's true: downcasting requires an object of polymorphic type, and RTTI to traverse the object's inheritance tree at runtime.

The other type of dynamic_cast is explained in the paragraph before that:

This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base), in the same way as allowed as an implicit conversion.

No RTTI is required here as an object's base(s) is/are always known statically.

So you only need to fully read the surrounding text in order to understand the context of the words you're reading.

I would note, however, that in my experience a compiler with RTTI disabled by default is basically unheard of. I'm not saying that none exist — there may be some niche, industry-specific compilers targeting embedded platforms that do this to save the programmer a few bytes in their Makefile. But the compilers that most people use (GCC, Clang, Visual Studio, ICC, Comeau) all, to the best of my knowledge, pack RTTI as standard and leave it on until you ask for it to be turned off.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Thank you does that mean that you have to use dynamic_cast with more caution than when using other casting operators, like static_cast? –  Jun 09 '17 at 09:37
  • @OfT: I don't think so. What sort of caution do you envisage? – Lightness Races in Orbit Jun 09 '17 at 10:27
  • I mean because that it COULD be that the compiler did not support dynamic_cast fully whereas maybe static_cast and other casting operators would work just fine.. –  Jun 09 '17 at 11:35
  • @OfT: I don't think that means you need any caution; [you should get a compilation error if you can't use `dynamic_cast` in the way you want](http://coliru.stacked-crooked.com/a/b4756f23182a9bb8). – Lightness Races in Orbit Jun 09 '17 at 12:07
  • Ahh okay great so I shouldn't hesitate to use the specific casting operator if it is the most appropriate for the given situation, such as dynamic_cast for polymorphic classes? –  Jun 09 '17 at 12:26
0

The author in the section mentioned by you referred to the cases when you are using dynamic_cast with polymorphic types: to be a little bit more precise, when you write something like dynamic_cast<X*>(p). In cases like that, you are going to need Run-Time Type Information so that dynamic_cast can be used at all (see the example below).

You can make the compiler disable the generation of such information about every class with virtual functions by using the mentioned compiler option, -fno-rtti, but it's rarely recommended.

"Other" cases are about the usage of dynamic_cast for void*s.

For example, consider the following code:

class A {
public:
  virtual ~A() = default;
};

class B : public A {};

int main()
{
  A *p = new B();
  void *pv = dynamic_cast<void*>(p);
  //B *pb = dynamic_cast<B*>(p);

  delete p;

  return 0;
}

If you compile the code with g++ test.cpp -std=c++11 -fno-rtti, it's gonna be just fine. But, if you do the same after uncommenting B *pb = dynamic_cast<B*>(p);, the compiler is going to give the following error message for this specific line: error: ‘dynamic_cast’ not permitted with -fno-rtti. Note that the cast to void* works even if using -fno-rtti (which has been set either manually or by default).

mindthegap
  • 323
  • 2
  • 7
  • 19
  • 3
    `dynamic_cast` can only be used with polymorphic types – M.M Jun 08 '17 at 22:34
  • @M.M Not entirely true. It can be used for non-polymorphic types in some cases. However, in all of those cases using `dynamic_cast` is pointless since an implicit conversion would do. (There may be some corner cases in template functions where this is useful.) – aschepler Jun 08 '17 at 22:40
  • @aschepler OK, I should say that downcasting via `dynamic_cast` can only be done with polymorphic types – M.M Jun 08 '17 at 22:52
  • Thanks for the comments, tried to extend my answer to reflect my point better. – mindthegap Jun 08 '17 at 23:43
-1

rtti is expensive at runtime and some embedded systems compile with flags, disabling it. All it gives you are dynamic_cast and typeid.

Therefore, I interpret

because you do not know if it is supported fully by the compiler

as

because your code could have been compiled with rtti disabled.

Vorac
  • 8,726
  • 11
  • 58
  • 101