2011-09-30 68 views
11

在阅读教材中的内容后,我有点困惑。关于代码:这是铸造还是建筑?

void doSomeWork(const Widget& w) 
{ 
    //Fun stuff. 
} 

doSomeWork(Widget(15)); 

doSomeWork()需要const Widget&参数。教科书Effective C++ III指出这会创建一个临时Widget对象传递给doSomeWork。它说,这可以被替换为:

doSomeWork(static_cast<Widget>(15)); 

为两个版本的石膏 - 第一仅仅是一个函数,C风格六名演员。我会认为Widget(15)会调用一个构造函数来获取一个整数参数。

在这种情况下执行构造函数吗?

回答

12

在C++中,这种表达式铸型的一种形式,至少在语法上。即您使用C++函数强制转换语法Widget(15)来创建Widget类型的临时对象。

即使你使用多参数的构造函数(如Widget(1, 2, 3))它仍然被认为功能铸符号的变化建立一个临时的(参见5.2.3节)

换句话说,你的“是这个演员或建筑“这个问题是错误的,因为它意味着演员和”建筑“之间的相互排斥。它们不是相互排斥的。实际上,每种类型转换(是一种明确的转换或更隐含的东西)只不过是目标类型的新临时对象(可能不包括某些引用初始化)的创建(“构造”)。

顺便说一句,功能强制符号是主要的C++符号。 C语言没有功能风格的演员表。

1

你说:

第一仅仅是一个函数,C风格铸显然

第一不会编译用C,这不是C风格。 C型看起来像(Widget)15。在这里,使用Widget::Widget(int)创建临时对象。

因此,它不是C风格的演员。

+1

@Constantinius:究竟是什么错误? – AnT

+0

我编辑了你的答案。 – 2011-09-30 15:11:27

-1

Yeeeah。你可以用

static_cast<Widget>(15) 

更换

Widget(15) 

因为它会被编译器替换回:d

当你施放intWidget编译器查找Widget::Widget(int);,并将其放置在那里。

5

短:是的。

长:

您可以自己始终测试的那些东西,这样做例如: -

#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); 
} 

其输出

W(1) 
W(2) 
W(3) 
+0

第一个不是演员。你试图展示什么? – MSalters

+2

@ MSalters:对于大多数类型而言,强制转换与创建(临时)对象没有区别。 – PlasmaHH

+1

@ MSalters:我认为他试图展现这种差异 – 2011-09-30 14:59:00

3

是,它既是:)。演员阵容是一个句法结构(即你输入的东西)。在这种情况下,作为演员的结果调用构造函数。就像一个构造函数被调用为输入

Widget w(15); 
3

两个Widget(15)static_cast<Widget>(15)的结果是铸件,或转换 运营商,如果你喜欢。通过将15转换为Widget,两者都创建指定的 类型的新对象。由于15没有任何 转换运算符,因此执行此转换的唯一方法是通过 分配必要的内存(在堆栈上)并调用适当的构造函数 。这实在是没有什么不同的是double(15)static_cast<double>(15),除了我们通常不认为 double为具有构造函数(但由此double是一个新的 对象,从15不同,其类型为int)。

0

是的,当然。任何只有一个参数的构造函数都将被视为CONVERSION CONSTRUCTOR。您的构造函数已经采用了一个参数int,以便编译器可以“隐式”调用此构造函数以匹配参数(值为15,即int)。

有一个简单的技巧来防止这种错误,只需在构造函数之前使用关键字explicit即可。

检查this了解更多信息。