【问题标题】:Overloaded Bool/String Ambiguity重载的布尔/字符串歧义
【发布时间】:2014-10-16 21:11:04
【问题描述】:

为什么 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 * 跳转到 string,而只是假设 bool 是最接近指针的东西?我唯一的选择是创建一个与字符串构造函数基本相同的显式 char * 构造函数吗?

【问题讨论】:

  • 我通常更喜欢显式转换。隐式转换有这样的问题。见stackoverflow.com/q/2346083/10077
  • 我不确定,但是:两种转换都是可能的(将指针转换为布尔检查空指针)。但是转换为 bool 是 built-in 转换,而转换为 string 是 user-defined 转换(通过隐式 c'tor)。现在,如果我没记错的话,内置的优先级高于用户定义的。

标签: c++ string casting boolean overloading


【解决方案1】:

如果你有 C++11,你可以使用委托构造函数:

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

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

【讨论】:

    【解决方案2】:

    A(string("hello"));
    

    它会给出预期的结果。

    为什么会这样?

    这是因为标准转换:

    • “hello”被理解为const char*指针
    • 此指针可以转换为bool(标准第 4.12 节:“(...) 指针 (...) 类型的纯右值可以转换为 bool 类型的纯右值。”
    • 不考虑从“hello”到string 的转换,因为标准的第 12.3 节解释说“类对象的类型转换可以由构造函数和转换函数指定。这些转换称为用户定义的转换”和“用户定义的转换仅在明确的情况下应用”。你不会有bool 构造函数std::string 转换会隐式完成。

    如何达到你的预期?

    只需为字符串添加缺少的构造函数:

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

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

    【讨论】:

    • 是的,但我不想每次都输入string(...)。我唯一的其他选择是创建一个以char const * 作为参数的构造函数吗?
    • 是的!我已经完成了额外的解释。
    【解决方案3】:

    选择过载方法时,这是编译器尝试的顺序:

    1. 完全匹配
    2. 促销
    3. 标准数值转换
    4. 用户定义的运算符

    指针不会提升为bool,但它会转换为boolchar* 使用 std 运算符转换为 std::string。请注意,如果 char* 在此列表中使用相同的数字来转换为 both boolstd::string 编译器应该选择哪种方法将是不明确的,因此编译器会抛出一个“模糊过载”错误。

    我会全力支持0x499602D2 的解决方案。如果你有 C++11,你最好打电话:A(char* s) : A(std::string(s)){} 如果您没有 C++11,那么我将创建一个 A(char* s) 构造函数并将 A(std::string) 构造函数的逻辑抽象为一个方法,并从两个构造函数中调用该方法。

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

    【讨论】:

      【解决方案4】:

      最近我也解决了这个问题,换个方式分享一下。

      您可以将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::stringconst char* 提供始终重载,也无需在客户端调用站点上构建std::string 的代码膨胀。

      我并不是说它更好,但它更简单。

      【讨论】:

      • 我遇到了同样的问题,但我想知道为什么 A("Hello");不给出警告,但 const char *b = "Hello";甲(乙);给出警告 4800:强制值为 bool 'true' 或 'false'?
      • 这也对我有用,并且对新的string_views 也非常有用。有关示例,请参见 here
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 2013-02-08
      • 1970-01-01
      • 2021-03-17
      • 2021-05-02
      • 1970-01-01
      • 2015-08-28
      相关资源
      最近更新 更多