Reputation: 2596
I came from Java, so when need to call a function like this:
struct A {
int a;
A(int a) : a(a){ }
};
A foo(A a){
return A(a);
}
I tend to write something like
A a = foo(A(10));
and it works perfectly fine. But I learnt that it can also be done in this way::
A a = foo(static_cast<A>(10));
I.e. it enforces the implicit conversion. So, as a rule of thumb should we alsways use static_cast
-style when we need to exploit implicit conversion? Or there are some cases where function/C-style casts may be necessary?
Upvotes: 1
Views: 120
Reputation: 12249
When you want to do a conversion from type A
to B
, you have two syntaxes to define the conversion:
class B
{
public:
B(A); # Conversion constructor.
};
or
class A
{
public:
operator B(); # Conversion operator.
};
For a case like:
void f(B b);
int main()
{
A a;
f(a);
}
If the first version exists, it creates a temporary object of class B
, using a
as parameter. If the second version exists (and you implement it, of course), it calls the operator B()
of class A
to create an object of type B
from a
. If both exists, the compiler throws you a message of ambiguity error.
About down/up-casting, implicit conversions allow upcasting (if source and target types are references/pointers), even if the target base is an innacesible (private) base class of the source. Implicit conversions also allow conversion from a non-const source type to a const target type, or also conversion from rvalue to lvalue and so on.
These are, in short, the rules of implicit conversions. A more complete guide (considering built-in versus user-defined types and built-in conversions) is here.
If you use the C++-casting:
f(static_cast<B>(a));
its nearly the same but with some differences: if B
is an innaccesible (private) base of a
, the cast isn't allowed. The other difference is that downcasting is allowed without runtime check (if B
is a derived class of A
it allows the casting, even if a
isn't actually an object of type B
). That is allowed because runtime check is slow, so, if you KNOW a
is actually of type B
, you can safely apply the casting without runtime check.
Other castings are:
const_cast<B>(a)
Only to change from const to non-const and viceversa.
reinterpret_cast<B>(a);
Cast everything. Nearly no rules involved. If a conversion from a
to B
doesn't exists, it just takes the memory region of a
and returns it as an object of type B
. Its the fastest cast alive.
dynamic_cast<B>(a);
Downcasting with runtime check (both types must be references or pointers). If the real type of a
isn't B
(not even a base class of the real type of a
), an exception or null pointer is thrown/returned (according to if a
or B
are references or pointers).
Lastly, the C-casting:
f((B)a);
What the C-casting does is to try different castings (except dynamic_cast
, and also allowing casting to innacesible base classes) and use the first which works. I would say the C-casting is as powerful as the implicit cast.
The explicit casting with syntax of funcion call:
f(B(a));
is equivalent to the C-casting in behaviour.
Upvotes: 2
Reputation: 106068
There are two separate aspects worth (re)consideration here: should A::A(int)
be left implicit, and how best to construct an A
to pass to foo
.
For the former, there's no way of deciding without knowing the usage A
should support, but it's generally recommended to err on the side of having explicit constructors if unsure.
For construction, use A(10)
(with C++11, A{10}
works too), or just 10
to rely on the implicit conversion. Note that A(10)
is a constructor call not a cast: there's no need to consider static_cast<>()
as a preferred casting notation. The old C-style cast notation is actually (T)
cast-expression
, per 5.4 [expr.cast] in the C++ Standard.
Upvotes: 2
Reputation: 249113
You never need C-style casts in C++. As for your examples, the most common way to write it would be this one:
A a = foo(A(10));
Upvotes: 3