【问题标题】:C++ : Ternary Operator (Conditional Operator) and its Implicit Type Conversion RulesC++:三元运算符(条件运算符)及其隐式类型转换规则
【发布时间】:2015-08-27 13:59:22
【问题描述】:

三元运算符的参数有隐式类型转换的规则吗?

三元运算符总是需要返回相同的类型。此类型仅由第二个和第三个参数 (1st ? 2nd : 3rd) 确定,因此两个参数都转换为此类型。这种类型是如何确定的?

更具体地说,我测试了一个例子:

class pointclass
{
    pointclass();

    pointclass( int i );    // (pointclass)(int)
    operator bool() const;  // (bool)(pointclass)
};

我有一个类 (pointclass),它支持从 intpointclass 的隐式转换以及从 pointclassbool 的隐式转换。

int i;
pointclass p;
bool b;

b ? p : i;  // (bool) ? (int)(bool)(pointclass) : (int)
b ? i : p;  // (bool) ? (int) : (int)(bool)(pointclass)

使用三元运算符,我比较pointclassint。编译器使用从pointclassbool 的隐式转换,然后使用从boolint 的标准转换。无论我是否交换第二个和第三个参数,这都完成了。 为什么不能将int 转换为pointclass

使用比较运算符要简单得多:

p == i;     // (pointclass) == (pointclass)(int)
i == p;     // (int) == (int)(bool)(pointclass)

参数的类型仅由第一个参数确定。

但是我不明白三元运算符的类型转换规则。对我来说,这似乎就像使用大多数转换的方式。

【问题讨论】:

  • 是的,规则在标准的[expr.cond]中。
  • 比我更精通标准方式的人可以给出权威的答案,但根据经验,它们会转换为可以转换为的“最接近”的常见类型。
  • 如果你认为 C++ 做的事情很时髦,请想想那些可怜的 Java 人。
  • 规则在 5.16 [expr.cond] 中列出。哪一个有问题?
  • 问题是转换为bool,它丢弃了几乎所有的信息。最好的方法是防止从 bool 成功进行隐式转换。

标签: c++ types implicit ternary


【解决方案1】:

引用MSDN:

条件表达式具有从右到左的结合性。首先 操作数必须是整数或指针类型。以下规则适用 到第二个和第三个操作数:

如果两个操作数属于同一类型,则结果为该类型。

如果两个操作数都是算术或枚举类型,则通常的算术转换(在算术转换中介绍)是 执行以将它们转换为通用类型。

如果两个操作数都是指针类型,或者如果一个是指针类型而另一个是计算结果为 0 的常量表达式,则指针 执行转换以将它们转换为通用类型。

如果两个操作数都是引用类型,则执行引用转换以将它们转换为公共类型。

如果两个操作数都是 void 类型,则公共类型是 void。

如果两个操作数是相同的用户定义类型,则通用类型就是该类型。

如果操作数具有不同的类型,并且至少有一个操作数具有用户定义的类型,则使用语言规则 确定常用类型。 (请参阅下面的警告。)

基本上,C++ 编译器会为第二个和第三个操作数寻找通用类型。如果它可以找到它,那就是结果类型。如果找不到,则会导致编译时错误。

如果要查看标准位置,可以查看规则in working draft for newest standard,5.16(第129页)。

不将 int 转换为 pointclass - 一般规则是您总是沿着层次结构向下,而不是向上 - 想象更高级的类层次结构;在某个地方,可能有几十种方法可以将这两种类型转换为其他类,但这真的是你想要的吗?此外,确定使用哪个类可能是不可能的。因此,我们很沮丧。

【讨论】:

  • 感谢您的回答。我理解,条件运算符总是向下转换层次结构,其中标准类型低于类。这些标准类型之间的隐式转换产生了一个问题。我可以通过将pointclass 和除bool 之外的所有标准类型之间的(隐式)转换运算符显式定义为protected 来防止这些转换。谢谢!
猜你喜欢
  • 2018-08-20
  • 1970-01-01
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
  • 2021-05-31
相关资源
最近更新 更多