2013-06-12 115 views
2

爲什麼下面的C++程序輸出「ABaBbAc」?C++運算符重載和參數化構造函數

#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; 
} 
+1

你會期望它做什麼? – Beta

+0

這是一個編程面試問題,我無法理解.. – RDX

+1

字符串中的小寫字母a和b表示A和B類型的相應對象resp被轉換爲某個int值 – damienh

回答

3

首先,ab是默認構造(以該順序),並且這導致AB要打印到標準輸出。

在此之後,程序的輸出可能與您正在觀察的程序(或可能正是您正在觀察的那個程序 - 請繼續閱讀)中的不同。

這是因爲operator +的操作數不需要按照確定的順序進行評估。只有在調用operator +之前,才允許它們進行評估(參見C++ 11標準的第1.9/15段)。

所以這個表達式:

(A)b 

將導致給定的結構類型B的目的A類型的臨時對象的。這怎麼可能?那麼,A有一個構造函數接受intB有一個用戶定義的轉換爲int

因此,從bint(1)的用戶定義轉換負責打印b。然後,由int(2)產生的A臨時建築負責打印A

對稱地,表達式:

(B)a 

會導致B類型的臨時對象,從a用戶定義轉化爲int的結果構造的構造。此轉換(3)負責打印a,而B的建設臨時(4)負責打印B

最終,從表達式(A)b(B)a的評價得到的兩種臨時對象被用作參數的operator +(5),它負責打印C

現在C++標準僅規定:

  • (1) - (4)之前必須評價(5)
  • (1)必須在(2)
  • (3被評估)必須在評估之前(4)

除此之外,評估的排序是未指定的。這意味着,輸出必須是這樣的:

AB????C 

其中問號應的輸出的可容許的排列替換(1),(2),(3)和(4)滿足上面指定的約束。

0

那麼,看代碼!

A的構造函數輸出字符A

B的構造函數輸出字符B

所以現在我們在「AB」

operator int()被稱爲轉換操作符,它允許在地方的整數要使用的類。所以當你打包(A)時,你打電話operator int(),其輸出a。與(B)

相同當您調用(B)a或者相反時,您正在創建類型爲A的臨時對象,再次調用構造函數。與(A)b轉換相同。

這就是aBbA的來源。

最後一點是operator +,它輸出c,但我認爲你的代碼是不正確的,因爲它似乎是大寫。

所以最終的輸出是ABaBbac

0

第2個字符是沒有brainers ..

我通過調試運行的代碼,並注意到+運營商的操作數在右操作數的順序進行評估,然後先左操作

所以對於(A)b +(B)a

(B)首先從左到右評估a執行它的B的構造函數,然後'cast到int。

類似地,對於左操作數

(A)的構造則b的INT鑄造。

然後+操作員被稱爲打印c