开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜