您能否解释为什么以下代码会编译并运行?这里的概念是什么?使用这种方法的局限性/要求是什么?
class string_wrapper
{
public:
string_wrapper(string i_string);
string m_value;
int m_length;
};
string_wrapper::string_wrapper(string i_string)
{
m_value = i_string;
m_length = i_string.length();
}
void bar(string_wrapper i_param)
{
cout << i_param.m_value << std::endl;
}
void foo()
{
string test_string = "test1";
bar(test_string);
}
int main()
{
test_function_b();
}
输出:
test1
我希望此代码无法编译。当bar仅采用string_wrapper参数时,foo()将字符串参数传递给bar()。但是,编译器很聪明,知道它可以将string参数用作string_parameter对象的构造函数的参数,然后大概将其作为实际参数传递给bar()。
这是C ++标准中的行为,还是我的编译器所独有的(在这种情况下,Visual Studio 2017版本15.9)?我可以用于进一步研究的任何见解或术语将不胜感激。
这里发生的是隐式构造。您正确地知道编译器“很聪明”,足以知道您可以从string_wrapper
中创建一个std::string
,因此自动为您创建。
要停止这种情况,您可以像这样使用explcit
关键字:
...
explicit string_wrapper(string i_string);
...
explicit
关键字告诉编译器您不希望它为string_wrapper
之外的对象自动构造std::string
对象。由于可以防止意外构造对象(尤其是在函数返回和传递参数时),因此可以阻止错误跟踪。
当对象只有一个非默认参数时可能会发生隐式构造(隐式转换也是您应该研究的东西)。它可以是功能强大的工具,并且可以允许代理类和透明API(即std::vector
的参考类)之类的东西。通常,除非不做设计决定,否则应声明单个参数(或单个非默认值)的构造函数(和转换运算符)explicit
。