C++隐式转换

23 c++

关于我最近回答的一些评论,在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
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

感谢Abhay提供报价.

Abh*_*hay 12

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

1类对象的类型转换可以由构造函数和转换函数指定.这些转换称为用户定义的转换,用于隐式类型转换(第4节),初始化(8.5)和显式类型转换(5.4,5.2.9).

2用户定义的转换仅在明确无误的情况下应用(10.2,12.3.2).转换遵守访问控制规则(第11条).模糊度解决(3.4)后应用访问控制.

3 [注意:有关在函数调用中使用转换的讨论以及下面的示例,请参见13.3. - 尾注]

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


Pie*_*ter 9

似乎已经达成共识:是的,你是对的.

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

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

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

 std::string s;
 s += 67;    // (1)
 s = s + 67; // (2)
Run Code Online (Sandbox Code Playgroud)

(1)编译和工作正常,operator+=是一个成员函数,模板字符参数已经通过实例化为std::strings(to char)推导出来.因此允许隐式转换(int- > char),导致s包含等效于67的char,例如在ASCII中这将成为'C'

(2)给出的编译器错误operator+被声明为免费功能,这里的模板字符参数在扣除使用.


sha*_*oth 8

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

连续两次转换可以使用转换运算符和参数化构造函数的组合来执行,但这会导致C4927警告 - "非法转换;已隐式应用多个用户定义的转换" - 在VC++中出于某种原因.


Max*_*ert 7

C++编程语言(第4版)(第18.4.3节)说

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

如果某些部分位于本机类型之间,那么"用户定义"部分听起来就像允许多次隐式转换一样.