【问题标题】:Why is "operator bool()" getting called if a class object needs conversion to int in C++?如果类对象需要在 C++ 中转换为 int,为什么会调用“operator bool()”?
【发布时间】:2017-11-28 05:29:31
【问题描述】:

我有一个以 int 作为参数的 some_func 函数调用。

int some_func(int);

class S {
public:
  S(int v) {
   a = v;
   }
  ...
 operator bool() const {
   return true;
 }
int a;
};  // class S doesn't define any "operator int"
S obj;
int x = some_func(obj); // some_func expected an int argument

在上面的代码中,some_func 需要 int 参数,但调用的是 S 类型的对象。因此它需要将其转换为“int”。

但是为什么它使用“operator bool”呢?它不应该产生编译错误,说明没有为类 S 指定正确的 int 转换方法吗?

如果我删除运算符 bool 定义,则程序无法编译并在 some_func 调用中给出有关参数类型不匹配的错误。

【问题讨论】:

  • A bool 值可隐式转换为 int,其值为 0(对于 false)或 1(对于 true)。参见例如this implicit conversion reference(尤其是关于integral promotion的部分)了解更多信息。
  • 我想我知道提升 bool 到 int 和隐式转换背后的一般想法。但这更微妙:存在从“S”到 int 的隐式转换(步骤 1),但隐式转换运算符不可用(showstopper 问题)。因此,正在使用另一个运算符(运算符 bool()),因为可以将“bool”提升为 int(步骤 2)。由于 showstopper 问题,无法进行第 1 步......(续......)
  • (..continued) 我认为 C++ 没有指定运算符 bool 而不是 bool 的什么提升(即当隐式转换运算符可以以某种方式用于进行“S”的转换时-> bool -> int 工作)。单独的积分促销在哪里完全涵盖了它?
  • 为了防止隐式转换,请使用explicit operator bool() - 自 C++11 起可用。

标签: c++ casting operator-overloading operators implicit-conversion


【解决方案1】:

boolean 在内部表示为整数。

true 定义为1(基本上除了0 之外的所有内容),false 定义为0

所以可以这样做:

if(true+false+true) 将产生 if(2),这将是 true,因为只有 if(0) 将是 false

【讨论】:

  • To nitpick: true 可以用除 0 以外的任何值表示。但是当 bool 转换为整数类型时,true 的任何表示都会转换为 1。
  • (我在之前的评论中发布了这个:)我认为 C++ 没有指定运算符 bool 的提升,而不仅仅是 bool (即当隐式转换运算符可以以某种方式用于转换“ S"-> bool -> int 工作)。单独的积分促销在哪里完全涵盖了它?
【解决方案2】:

C++ 有隐式转换。通过定义转换运算符operator bool(),您可以使 S 隐式转换为 bool。这是用户定义的转换。一次转换可以由一系列转换组成(其中只有一个可能是用户定义的)。

虽然没有从 S 到 int 的直接转换,但是有一个从 bool 到 int 的内置转换(这是一个整数提升,true 转换为 1,false 转换为 0)。因此转换序列 S -> bool -> int 是有效的,因此 S 可以隐式转换为 int。


PS。如果您想在调用该函数时防止从 bool 进行隐式转换,您可以声明一个已删除的重载,重载决议会首选该重载:

int some_func(bool) = delete;

【讨论】:

【解决方案3】:

每当编译器可能需要将表达式转换为另一种类型时,特别是对于函数调用的每个参数,它都会尝试:

  1. 可选的标准转换序列。
  2. 可选的用户定义转换。
  3. 可选的标准转换序列。

标准转换序列是由语言定义的,例如算术到算术的转换、指针转换等。用户定义的转换是涉及可以采用一个参数的构造函数或像 @987654322 这样的转换函数的转换序列@。

因此,在您的示例中,它没有找到标准转换,然后是您的 S::operator bool() 用户定义的转换,然后是从 boolint 的标准转换。

更多血腥细节,见the cppreference page on implicit conversions

【讨论】:

    【解决方案4】:

    BoolInt 都是 data-types。数据类型可以隐式或显式转换。用户看不到隐式转换。

    当你定义时:

    operator bool() const {
       return true;
     }
    

    然后S 被隐式转换为bool。您可以将其显式转换为int。但请注意,虽然显式转换请记住 bytes 的范围,并且不要将较大的数据类型转换为较小的数据类型,否则您会丢失数据,因为某些字节(较大的数据类型 - 较小的数据类型)会被截断。

    在您的问题中,integers 被转换为boolean(隐式转换)这里除0 之外的数字将存储为true,即数字形式为1 和数字@987654336 @ 本身将被视为false,因此将存储为0

    您可以通过定义自己的显式运算符来防止这种隐式转换。请参阅here 或者您可以声明删除重载。

    请参阅here 了解类似问题。我想你会在你寻求的解决方案中学到一些东西。

    【讨论】:

      猜你喜欢
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 2010-11-21
      • 1970-01-01
      • 2011-06-25
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多