Reputation: 1435
When initializing with a pointer a nullptr can be ambiguous if there are multiple constructors accepting a pointer argument.
You can solve this by casting C cast or static_cast, example:
#include <iostream>
#include <cstddef>
using namespace std;
struct A{
A(int*){ cout << "int constructor" << endl;}
A(double*) { cout << "double constructor" << endl;}
};
struct B{
B(std::nullptr_t) { cout << "nullptr constructor" << endl;}
B(int*){ cout << "int constructor" << endl;}
B(double*) { cout << "double constructor" << endl;}
};
int main(){
//A a(nullptr); constructor is ambiguous
A a1((int*)nullptr);// int constructor
A a2(static_cast<double*>(nullptr));// double constructor
B b(nullptr);// nullptr constructor
return 0;
}
I included B to illustrate that a constructor with std::nullptr_t exist and is possible but for this question let's focus on A.
From "Why use static_cast(x) instead of (int)x?" I understand the most dangerous thing about C cast being you don't know which will be used:
The main reason is that classic C casts make no distinction between what we call static_cast<>(), reinterpret_cast<>(), const_cast<>(), and dynamic_cast<>(). These four things are completely different.
Are any of these casts unsafe for a nullptr or can you safely use the C-style cast?
Upvotes: 0
Views: 3438
Reputation: 5613
I feel that if the class allow multiple pointer types to construct then the class author should take design responsibility for explicit null pointers.
The default position is that null pointers are not handled, which is perfectly valid. The author can add a nullptr_t or no-args constructor if they want to handle explicit null pointers, but if not, the user should take it as a firm design warning.
Upvotes: 0
Reputation: 25895
A reinterpret
cast is unsafe irrespective of what you're casting - the point is you're forcing the compiler to ignore it's own set of (very good) rules and trust your (usually wrong) intuition.
I consider dynamic_cast
ing also somewhat hazardous since it allows you to compile down-casting and side-casting. Sometimes when just starting to work with this this can cause confusing NULL pointers appearing or run-time errors.
In your example it doesn't matter since the conversion is trivial, so you "can" use anything, but you probably shouldn't. The C-style case will probably be static since it's hard-coded in compilation time, so in your case it won't matter (but you can't be sure! it's not guaranteed!). This is more of a be safe convention - use static_cast
since that's what you want to do, and that's the way to guarantee it. If your code becomes more advance/complex/difficult the "be safe" rule can really save you from nasty bugs.
In general, C++
should contain no native C
, at least as a beginner, probably most of the time.
Upvotes: 2