Is this a cast or a construction?
I'm a little confused after reading something in a textbook. Regarding the code:
void doSomeWork(const Widget& w)
{
//Fun stuff.
}
doSomeWork(Widget(15));
doSomeWork()
takes a const Widget&
parameter. The textbook, Effective C++ III, states that this creates a temporary Widget object to pass to doSomeWork. It says that this can be replaced by:
doSomeWork(static_cast<Widget>(15));
as both versions are casts - 开发者_如何学Cthe first is just a function-style C cast apparently. I would have thought that Widget(15)
would invoke a constructor for widget taking one integer parameter though.
Would the constructor be executed in this case?
In C++ this kind of expression is a form of a cast, at least syntactically. I.e. you use a C++ functional cast syntax Widget(15)
to create a temporary object of type Widget
.
Even when you construct a temporary using a multi-argument constructor (as in Widget(1, 2, 3)
) it is still considered a variation of functional cast notation (see 5.2.3)
In other words, your "Is this a cast or a construction" question is incorrectly stated, since it implies mutual exclusivity between casts and "constructions". They are not mutually exclusive. In fact, every type conversion (be that an explicit cast or something more implicit) is nothing else than a creation ("construction") of a new temporary object of the target type (excluding, maybe, some reference initializations).
BTW, functional cast notation is a chiefly C++ notation. C language has no functional-style casts.
Short: Yes.
Long:
You can always test those things yourself, by doing e.g.:
#include <iostream>
struct W
{
W( int i )
{
std::cout << "W(" << i << ")\n";
}
};
int main(int argc, const char *argv[])
{
W w(1);
W(2);
static_cast<W>(3);
}
which is outputting
W(1)
W(2)
W(3)
Yes, it is both :). A cast is a syntactic construct (i.e. something you type). In this case, a constructor is invoked as a consequence of the cast. Much like a constructor would be invoked as a consequence of typing
Widget w(15);
Both Widget(15)
and static_cast<Widget>(15)
are casts, or conversion
operators, if you prefer. Both create a new object of the designated
type, by converting 15
into a Widget
. Since 15
doesn't have any
conversion operators, the only way to do this conversion is by
allocating the necessary memory (on the stack) and calling the
appropriate constructor. This is really no different that double(15)
and static_cast<double>(15)
, except that we usually don't think of
double
as having a constructor (but the resulting double
is a new
object, distinct from the 15
, which has type int
).
You said:
the first is just a function-style C cast apparently
The first would not compile in C, it's not C-style. C-style looks like (Widget)15
. Here, the temporary object is created, using Widget::Widget(int)
.
Therefore, it is not a C-style cast.
Yes, of course. Any constructor takes a single parameter would be considered as CONVERSION CONSTRUCTOR. Your constructor is already taking a single int
parameter, so that the compiler can "implicitly" call this constructor to match the argument (with the value 15
, which is int
).
There is a simple trick to prevent such errors, just use the keyword explicit
before your constructor.
Check this for more information.
Yeeeah. You can replace
Widget(15)
with
static_cast<Widget>(15)
Because it will be replaced back by compiler :D
When you cast int
to Widget
compiler looks for Widget::Widget(int);
and place it there.
精彩评论