Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In c++11, does dynamic_cast return nullptr or 0?

I want to check the result of dynamic_cast. In c++11 (or c++0x, for compilers that support nullptr), should I compare against nullptr or 0?

Does it matter, and if so, why?

Is the result compiler-dependent?

like image 617
Patrick Avatar asked May 16 '13 14:05

Patrick


People also ask

What is the dynamic_cast operator used for?

The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .

Why does dynamic_cast return null?

If the cast is successful, dynamic_cast returns a value of type new-type. If the cast fails and new-type is a pointer type, it returns a null pointer of that type. If the cast fails and new-type is a reference type, it throws an exception that matches a handler of type std::bad_cast.

What does dynamic_cast int *>( return if the cast is valid?

If it is, dynamic_cast<Type*> returns a pointer; otherwise it returns NULL.

What is the use of dynamic_cast in C++?

dynamic_cast: This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritance when you cast from base class to derived class.


2 Answers

Both the constant nullptr (which is of type nullptr_t) and the constant 0 will implicitly convert to the null value of any pointer type. So comparing against either one will work and is technically OK. By the way, this means that dynamic_cast return neither one, it returns the null value for the particular pointer type.

It's probably best to get in the habit of using nullptr rather than 0. As far as I know, it's only really necessary for proper overload resolution (e.g. one overload takes int and another takes char*). For consistency, avoiding 0 will be best.

What do I mean by "the null value of a pointer type"?

Consider a variable char * ptr. It's type is (unsurprisingly) char *. But the type of nullptr is the special type nullptr_t. So when we write something like ptr = nullptr, some technical things must happen

  1. nullptr must be implicitly converted to char *.
  2. The result of this conversion is set as the new value of ptr.

The null value for char * is the result of converting nullptr to char *. Conceptually, it's still nullptr, but with a different type (char *). This null value is distinct from the null value of int * or string * or any other pointer type. We tend to think of these null values as just nullptr (or 0), but each one is really a distinct value from a different type. (By the way, the same conversion happens for comparison using ==).

Although this may sound like nitpicking details, it's very important in overload resolution:

void foo(char * ptr) { ... }
void foo(int i) { ... }
void foo(nullptr_t ptr) { ... }

int main()
{
    foo(0); // Calls void foo(int), since 0 is an int
    foo(nullptr); // Calls void foo(nullptr_t), since nullptr is a nullptr_t
    foo(new char('c')); // Calls void foo(char *), since new char('c') is a char*
}

or when assigning unrelated null values:

char * c_ptr = nullptr; // Okay
int * i_ptr1 = nullptr; // Okay
int * i_ptr2 = c_ptr;   // COMPILER ERROR HERE
like image 140
Ken Wayne VanderLinde Avatar answered Jan 22 '23 04:01

Ken Wayne VanderLinde


Evaluate the result in a boolean context:

Base * p = get();

if (Derived * q = dynamic_cast<Derived *>(p))
{
    q->derived_method();
}
else
{
    // *p isn't of type Derived
}

(This works in any version of C++.)

like image 22
Kerrek SB Avatar answered Jan 22 '23 02:01

Kerrek SB