2

为什么下面的 C++ 程序输出“ABaBbAc”?

#include "stdafx.h"
#include <iostream>

using namespace std;

class A {
public:
    int i;
    A(int j=0):i(j)
    {
        cout<<"A";
    }
    operator int()
    {
        cout<<"a";
        return 2;
    }
};

class B {
public:
    B(int j=1):i(j){
        cout<<"B";
    }
    operator int() {
        cout<<"b";
        return 3;
    }
    int i;
};

int operator+(const A&a, const B&b){
    cout<<"C";
    return a.i + b.i;
}

int main()
{
    A a;
    B b;

    int i = (A)b + (B)a;
    return 0;
}
4

3 回答 3

3

首先,a并且b是默认构造的(按此顺序),这会导致AB打印到标准输出。

在此之后,程序的输出可能与您正在观察的输出不同(或者可能正是您正在观察的输出 - 请继续阅读)。

这是因为 的操作数operator +不需要按确定的顺序计算。它们仅被授予在operator +调用之前进行评估(请参阅 C++11 标准的第 1.9/15 段)。

所以这个表达式:

(A)b

A给定类型的对象,将导致构造一个类型的临时对象B。这怎么可能?好吧,A有一个构造函数接受int, 并且B有一个用户定义的转换为int.

因此,用户定义的从bint(1) 的转换负责打印b. 然后,由A生成的临时构造int(2) 负责打印一个A.

对称地,表达式:

(B)a

将导致构造一个类型为 的临时对象,该对象是B根据用户定义的转换结果构造的ainto int。这个转换(3)负责打印a,而B临时(4)的施工负责打印B

最终,由表达式求值产生的两个临时(A)b变量(B)a被用作operator +(5) 的参数,它负责打印 a C

现在 C++ 标准只指定:

  • (1)-(4) 必须在 (5) 之前评估
  • (1) 必须在 (2) 之前进行评估
  • (3) 必须在 (4) 之前评估

除此之外,评估的顺序是未指定的。这意味着输出必须类似于:

AB????C

问号应替换为满足上述约束的 (1)、(2)、(3) 和 (4) 的输出的可接受排列。

于 2013-06-12T17:05:38.367 回答
0

好吧,看代码!

类的构造函数A输出 character A

类的构造函数B输出 character B

所以现在我们在“AB”

operator int()称为转换运算符,它允许使用类代替整数。因此,当您包装时,(A)您正在调用operator int()which outputs a。与(B)

当您调用(B)a或相反时,您正在创建一个临时对象 type A,再次调用构造函数。与(A)b转换相同。

这就是它的aBbA来源。

最后一件事是operator +,它输出c,尽管我认为您的代码不正确,因为它似乎是大写的。

所以最终的输出是ABaBbac

于 2013-06-12T17:09:58.947 回答
0

前两个字符是显而易见的..

我通过调试器运行代码,并注意到 + 运算符的操作数首先按右操作数的顺序进行评估,然后是左操作数

所以对于 (A)b+(B)a

(B) a 首先从左到右求值,执行其 B 的构造函数,然后将 a' 强制转换为 int。

同样对于左操作数

(A) 的构造函数,然后是 b 的 int 类型转换。

然后 + 运算符称为打印 c

于 2013-06-12T17:13:02.743 回答