构造函数解析顺序问题
考虑 T 的以下构造函数:
struct T {
T(const bool) { std::cout << "T(const bool)" << endl; }
T(const std::string&) { std::cout << "T(const std::string&)" << endl; }
};
T t("");
- 为什么在构造 t 时
T(const bool)
优先于T(const std::string&)
? 由于上述优先顺序可能会给希望调用
T(const std::string&)
的用户造成混乱,我该怎么做才能让T(const std::string&) )
在将字符串文字传递给 T 的构造函数时隐式调用。目前我发现的唯一解决方法是添加另一个构造函数,该构造函数具有最高优先级:T(const char* s) { std::cout << “T(const char*)”<<结束; *这= std::string(s); }
除上述之外解决方案,声明
显式 T(const bool)
以避免混淆并不能解决上述问题:在这种情况下,虽然现在禁止使用T t = ""
,但为什么形式是T t("")
仍然允许并调用T(const bool)
吗?
Consider the following constructors for T:
struct T {
T(const bool) { std::cout << "T(const bool)" << endl; }
T(const std::string&) { std::cout << "T(const std::string&)" << endl; }
};
T t("");
- Why does
T(const bool)
take precedence overT(const std::string&)
when constructing t? Since the above precedence might cause confusion to users expecting
T(const std::string&)
to be called, what can I do to haveT(const std::string&)
implicitly called when passing string literals to the constructor of T. For now the only work around I have found is to add another constructor, which takes the highest precedence:T(const char* s) { std::cout << "T(const char*)" << endl; *this = std::string(s); }
Apart from the above solution, declaring
explicit T(const bool)
to avoid confusion does not solve the above problem: in this case, althoughT t = ""
is now prohibited, why is the formT t("")
is still allowed and does callT(const bool)
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么在构造
t
时T(const bool)
优先于T(const std::string&)
?""
的类型为char[1]
;这可以通过数组到指针的转换隐式转换为char const*
。指针可以隐式转换为bool
,所有非空指针都变为true
,所有空指针都变为false
。这些都是“内置”标准转换。char const* ->; std::string
转换是用户声明的转换:它利用带有char const*
的std::string
转换构造函数。在重载解析期间,标准(“内置”)转换优于用户声明的转换,因此采用
bool
的构造函数在这里比采用std::string< 的构造函数更匹配/代码>。
目前我发现的唯一解决方法是添加另一个构造函数
这听起来像是一个合理的解决方案;对于您所描述的简单场景来说,这当然是最直接的解决方案。不过,您对
*this
的赋值有点笨拙;最好让两个构造函数都委托给某个初始化函数。或者,您可以将带有
enable_if
的模板用于您想要禁止转换的任何构造函数:此构造函数只能使用
bool
参数进行调用,而不能使用其他参数。您可以在 Boost、C++ TR1 或 C++0x 中找到enable_if
和is_same
。您还可以使用!is_pointer
、is_integral
或其他一些类型特征组合来允许使用某些其他参数类型,但不允许使用char const*
。或者,作为另一种选择,您可以完全避开
bool
并使用您自己的枚举,以及与构造函数的true
和false
对应的枚举器。这是否有意义取决于您的用例。声明
显式 T(const bool)
来避免并不能解决上述问题...为什么形式T t("")
仍然被允许并且确实callT(const bool)
?explicit
仅不允许隐式转换为T
。T t("");
根本没有到T
的转换;它通过将参数""
传递给最匹配的构造函数来构造对象t
,从而直接初始化对象t
。Why does
T(const bool)
take precedence overT(const std::string&)
when constructingt
?""
is of typechar[1]
; this is implicitly convertible tochar const*
via the array-to-pointer conversion. A pointer is implicitly convertible tobool
, with all non-null pointers becomingtrue
and all null pointers becomingfalse
. These are both "built-in" standard conversions.The
char const* -> std::string
conversion is a user-declared conversion: it utilizes a converting constructor ofstd::string
that takes achar const*
.The standard ("built-in") conversions are preferred over user-declared conversions during overload resolution, so the constructor taking
bool
is a better match here than the one takingstd::string
.For now the only work around I have found is to add another constructor
That sounds like a reasonable solution; certainly the most straightforward solution for the simple scenario you describe. Your use of assignment to
*this
is a bit clumsy, though; it would be better either to have both constructors delegate to some initialization function.Alternatively, you could use a template with
enable_if
for any constructors for which you would like to disallow conversions:This constructor will only be callable with a
bool
argument and nothing else. You can findenable_if
andis_same
in Boost, C++ TR1, or C++0x. You could also use!is_pointer
,is_integral
, or some other combination of type traits to allow for some other argument types but notchar const*
.Or, as another alternative, you might eschew
bool
altogether and use your own enumeration with enumerators corresponding totrue
andfalse
for the constructor. Whether this makes sense depends on your use case.Declaring
explicit T(const bool)
to avoid does not solve the above problem...why is the formT t("")
is still allowed and does callT(const bool)
?explicit
only disallows implicit conversions toT
.T t("");
has no conversions toT
at all; it directly initializes the objectt
by constructing it with the argument""
passed to whichever constructor matches best.""
可以转换为std::string
和bool
。问题是,它会以哪种方式转换?
std::string
的转换是用户定义的转换。bool
是标准转换。所以答案是,标准转换比用户定义的转换具有更高的优先级。因此
""
将转换为bool
。示例,
输出:
在线演示: http://www.ideone.com/5Bt0K
在上面的演示中,
10
可以转换为A
和bool
两者。由于转换为bool
是标准转换,因此它会转换为bool
,而不是A
。""
can convert to bothstd::string
andbool
.The question is, which way will it convert?
std::string
is a user-defined conversion.bool
is a standard conversion.So the answer is, standard conversion has higher precedence over user-defined conversion. So
""
will convert tobool
.Example,
Output:
Online demo : http://www.ideone.com/5Bt0K
In the above demo,
10
can convert toA
andbool
both. Since converting tobool
is a standard conversion, it converts intobool
, instead ofA
.因为如果内置转换可用,则不会考虑用户定义的转换。
使用第三个构造函数,该构造函数采用
const char*
。没有更好的办法了。Because a user-defined conversion is not considered if a built-in one is available.
Use the third constructor, one that takes
const char*
. There's no better way.