2014-10-16 121 views
8

为什么C++将字符串文字转换为布尔值而不是字符串?重载布尔/字符串歧义

#include <iostream> 

using namespace std; 

class A 
{ 
    public: 
     A(string v) 
     { 
      cout << v; 
     } 

     A(bool v) 
     { 
      cout << v; 
     } 
}; 

int main() 
{ 
    A("hello"); 
    return 0; 
} 

输出:1

是因为编译器是不是足够聪明,使从字符*串跳跃和而只是假设布尔是最接近的指针?我唯一的选择是创建一个明确的char *构造函数,它基本上和字符串构造函数完全一样吗?

+1

我通常更喜欢明确的转换。隐式转换有这样的陷阱。请参阅http://stackoverflow.com/q/2346083/10077 – 2014-10-16 21:18:23

+0

我不确定但是:两种转换都是可能的(将指针转换为布尔检查空指针)。但转换为布尔是*内置*转换,而字符串是*用户定义的* convesion(通过隐式c'tor)。现在,如果我没有记错,内置插件比用户定义的优先级更高。 – leemes 2014-10-16 21:19:03

+1

可能重复的[C++方法重载不工作](http://stackoverflow.com/questions/14770252/c-method-overload-not-working) – 2014-10-16 21:57:26

回答

12

如果有C++ 11可以使用一个委派构造:

A(char const* s) : A(std::string(s)) { } 

其原因被选择在一个用于std::string转换构造函数布尔是因为转换从char const*bool是标准转换,而std::string是用户定义的转换。标准转换的排名高于用户定义的转化。

3

随着

A(string("hello")); 

它会给预期的结果。

这是为什么?

这是因为标准的转化:

  • “你好”被理解为一个const char*指针
  • 这个指针可以被转换为标准的bool(第4.12:“的prvalue (...)指针(...)类型可以转换为bool类型的prvalue。“
  • 从”hello“到string的转换不被考虑,因为标准的第12.3节解释为”类对象的类型转换可以由构造函数和转换函数指定。这些转换被称为用户定义的转换“和”他们是毫不含糊的地方用户定义的转换只适用”你会不会有bool构造的std::string转换将被隐含完成。

如何让你的预期

只需添加缺少的构造函数的字符串litterals什么?

A(const char* v) 
{ 
    cout << v; // or convert v to string if you want to store it in a string member 
} 

当然,不是从头开始重写构造函数,而是可以在另一个答案中选择由0x499602D2建议的委托。

+0

是的,但我不想输出'字符串(。每次。我唯一的选择是创建一个将'char const *'作为参数的构造函数吗? – RPGillespie 2014-10-16 21:31:01

+0

是的!我完成了额外的解释。 – Christophe 2014-10-16 22:07:59

2

当选择一个重载方法这是编译器试图顺序:

  1. 精确匹配
  2. 促进
  3. 标准数值转换
  4. 用户定义的运算符

指针不会促销到bool,但它确实转换为bool。 A char*使用std运营商转换为std::string。请注意,如果char*在此列表中使用相同的编号转换为boolstd::string这将是不明确的编译器应该选择哪种方法,因此编译器会引发“模糊过载”错误。

我会把我的体重放在0x499602D2的解决方案后面。如果你有C++ 11,最好的办法是打电话给:A(char* s) : A(std::string(s)){} 如果你没有C++ 11,那么我会创建一个A(char* s)的构造函数,并将构造函数的逻辑抽象成一个方法并从两个方法中调用该方法构造函数。

http://www.learncpp.com/cpp-tutorial/76-function-overloading/

2

最近我通过这个问题也让我分享另一种方式。

您可以将bool构造函数更改为unsigned char。所以字符串文字的衰减和隐含转换不会发生,并且std::string构造函数发生。

class A 
{ 
public: 
    A(string v) 
    { 
     cout << v; 
    } 

    A(unsigned char v) 
    { 
     cout << static_cast<bool>(v); 
    } 
}; 

int main() 
{ 
    A("Hello"); // <- Call A(string) 
    A(false); // <- Call A(unsigned char) 
} 

这样你就不需要总是提供给超载和std::string既不const char*使代码膨胀在客户端调用点构建std::string

我不认为这样做更好,但更简单。

+0

我有同样的问题,但我想知道为什么A(“你好”);不会给出警告,但const char * b =“Hello”; A(B);给出警告4800:强制值为bool'true'或'false'? – 2017-02-09 11:10:50

+0

这也适用于我,对于新的'string_view'也非常有用。例如,请参阅[这里](https://godbolt.org/g/1uCwR2)。 – Claudius 2018-02-08 09:51:42