2011-10-29 35 views
2

我一直被教導說類的實例語法

1. Class c(arg); 

2. Class c = arg; 

是兩個完全等效的語句,但看這情形。

#include <iostream> 

class Intermediary { 
}; 

class Left { 
    public: 
    Left(const Intermediary &) { 
     std::cout << __PRETTY_FUNCTION__ << std::endl; 
    } 
}; 

class Right { 
    public: 
    // The argument is there just so that the example can work, see below 
    Right(int) { 
     std::cout << __PRETTY_FUNCTION__ << std::endl; 
    } 

    operator Intermediary() const { 
     std::cout << __PRETTY_FUNCTION__ << std::endl; 

     return Intermediary();  
    } 
}; 

現在,如果我這樣做:

Left l = Right(0); 

編譯器會抱怨

error: conversion from Right to non-scalar type Left requested 

但是,如果我這樣做:

Left l(Right(0)); 

然後,一切都編譯並輸出是

Right::Right(int) 
Right::operator Intermediary() const 
Left::Left(const Intermediary&) 

但是,如果我這樣做:

Left l = (Intermediary)Right(0); 

然後一切重新編譯和輸出就像上面的一個。

所以很明顯

1. Class c(arg); 

2. Class c = arg; 

是不一樣的,但爲什麼不呢,這有什麼區別?我在網上找不到任何東西。

+0

答案是您被教導錯誤。 –

回答

5

我總是被教導說Class c(arg);Class c = arg;是兩個完全等同的陳述,但看看這種情況。

原來,他們是不等價的。第一個構建Class carg的,而第二個構建一個Classarg的,然後複製構建體Class c出來。請注意,允許執行該副本,並且通常會執行該副本。

Left l = Right(0); 

這需要從RightIntermediary轉換,和一個從IntermediaryLeft。這兩個連續的用戶定義的轉換是標準所不允許的,您必須至少在其中一個顯式地執行以下操作:

Left l = (Intermediary)Right(0); 
+0

+1:對,爲了清晰起見,(1)語法沒有這個問題,因爲只有從'Right'到'Intermediary'的轉換。 –

+1

好吧,我想了很多,但據說我在網上找不到任何東西,而且我也嘗試實現類'Left'的拷貝構造函數,編譯時使用-O0,以防編譯器忽略它,但我仍然沒有被引用的跡象。 現在我想知道:爲什麼標準要求那些不是等價的陳述?是否有任何技術原因爲什麼它必須如此? –