C ++隐式转换

时间:2009-05-15 07:52:49

标签: c++

对我最近的回答What other useful casts can be used in C++的一些评论表明,我对C ++转换的理解是错误的。只是为了澄清这个问题,请考虑以下代码:

#include <string>

struct A {
    A( const std::string & s ) {}
};

void func( const A & a ) {
}

int main() {
    func( "one" );                  // error
    func( A("two") );           // ok
    func( std::string("three") );   // ok
}

我的断言是第一个函数调用是一个错误,因为没有从const char *到A的转换。有一个从字符串到A的转换,但是使用它会涉及多个转换。我的理解是这是不允许的,这似乎是由g ++ 4.4.0&amp; Comeau编译器。使用Comeau,我收到以下错误:

"ComeauTest.c", line 11: error: no suitable constructor exists 
      to convert from "const char [4]" to "A"
      func( "one" );                    // error

如果你能指出我错在哪里,无论是在这里还是在原始答案中,最好是参考C ++标准,请这样做。

C ++标准的答案似乎是:

  

最多一个用户定义的转化   (构造函数或转换函数)   隐式应用于单个值。

感谢Abhay提供报价。

4 个答案:

答案 0 :(得分:12)

我认为尖锐的答案是准确的。标题为“转换”的C ++标准(SC22-N-4411.pdf)第12.3.4节明确规定只允许一个隐式的用户定义转换。

  

1类对象的类型转换可以通过指定   构造函数和转换   功能。这些       转换称为用户定义的转换并被使用   用于隐式类型转换(Clause   4),为       初始化(8.5),以及显式类型转换(5.4,   5.2.9)。

     

2用户定义的转换仅适用于它们的位置   明确的(10.2,12.3.2)。   转换遵守       访问控制规则(第11条)。之后应用访问控制   歧义解决方案(3.4)。

     

3 [注意:有关转换使用的讨论,请参见13.3   在函数调用和示例中   下面。 -结束       注意]

     

4最多一个用户定义的转换(构造函数或转换   function)隐式应用于a   单       值。

答案 1 :(得分:9)

由于似乎已达成共识:是的,你是对的。

但是由于这个问题/答案可能会成为C ++隐式转换在stackoverflow上的参考点,我想为模板参数添加规则是不同的。

对于用于模板参数推断的参数,不允许隐式转换。这可能看起来很明显,但仍然会导致微妙的怪异。

例如,std :: string加法运算符

 std::string s;
 s += 67;    // (1)
 s = s + 67; // (2)

(1)编译并正常工作,operator+=是一个成员函数,模板字符参数已经通过实例化std::string获得s(char)来推断。因此允许隐式转换(int - &gt; char),结果s包含等效于67的char,例如在ASCII中,这将成为'C'

(2)给出编译器错误,因为operator+被声明为自由函数,这里模板字符参数 用于演绎。

答案 2 :(得分:8)

这是真的,只允许一次隐式转换。

连续两次转换可以使用转换运算符和参数化构造函数的组合执行,但这会导致C4927 warning - “非法转换;已隐式应用了多个用户定义的转换” - VC ++是有原因的。

答案 3 :(得分:7)

The C++ Programming Language(第4版)(第18.4.3节)说

  

只有一个级别的用户定义   隐式转换是合法的

“用户定义”部分听起来好像有些隐式转换可能是允许的,如果有些是本机类型之间的。