2013-02-05 24 views
2

爲什麼我不能分配給構造函數,何時可以分配給一個看起來像構造函數的函數?賦值給構造函數? (如元組層)

例子:

struct Bar { 
    Bar() : b_(false) {} 
    Bar(bool b) : b_(b) {} 
}; 

struct Foo { 
    Foo(Bar const & bar) : bar_(bar) {} 
    Foo operator=(Foo const & f) { return Foo(f.bar_); } 
    const Bar & bar_; 
} 

Foo bool_to_foo(bool b) { return Foo(Bar(b)); } 

Foo MakeFoo(Bar const & bar) { return Foo(bar); } 

爲什麼這個工作:

Bar bar; 
MakeFoo(bar) = bool_to_foo(true); 

當這不起作用?

Bar bar; 
Foo(bar) = bool_to_foo(true); // Error: 'bar': redefinition; different basic types 

MakeFoo(。)和Foo()具有相同的簽名,和相同的功能。

構造函數有什麼特別之處?

+1

你永遠不能「分配給一個功能」。雖然你可以分配給一個函數對象! –

+0

噢,當你在你的代碼的表達式中看到'Foo()'時,它就是_never_「構造函數」。直接調用或引用構造函數是不可能的。 –

+2

您不會在代碼中「分配給函數」,而是嘗試分配函數的返回值。 – PlasmaHH

回答

8

這條線:

Foo(bar) = bool_to_foo(true); 

沒有做什麼,你認爲它。它確實而不是聲明瞭一個用bar初始化的臨時對象。 它實際上做的是聲明Foo類型的名爲bar的對象,並使用值bool_to_foo(true)對其進行初始化。既然你已經有一個名爲bar範圍的對象,這是一個重新定義

Foo bar = bool_to_foo(true); 

在這個意義上,它是完全等價。


如果你還想做什麼你正在嘗試做的,你可以嘗試:

Foo((0,bar)) = bool_to_foo(true); 

但是,因爲這是既醜陋和混亂,我不會再形容了。

+0

's/does /沒有/' –

+0

@LightnessRacesinOrbit's/d/D/g':P –

+0

@LightnessRacesinOrbit - thanks。 –

0

​​函數返回一個對象,然後可以分配給對象(雖然我懷疑編譯器警告會抱怨分配給臨時)。但是,正如你所猜測的那樣,C++標準爲構造者提供了特殊的處理。雖然我不完全確定,但我懷疑= bool_to_foo(true)部分被視爲初始化,而不是賦值。這會導致錯誤,因爲foo沒有拷貝構造函數。

羅布還與Foo(酒吧)交易達成了一致。 C++語法有時可能很奇怪。

在任何情況下,這些形式中的任何一種都是不好的做法 - 分配給右值可能是不是你想要的,如果是的話很可能會混淆人。

+0

@Robert - C++中的「壞習慣」似乎是Haskell中的SOP ......他們似乎一直分配給類型構造函數。試圖分支到FP世界! –

+1

@DavidH:Haskell真棒。但風格/實踐並不跨越語言。在C++中,這個語法意味着與Haskell中的使用完全不同。在C++中,'MakeFoo(bar)= baz(quuz)'的含義是該表達式*的目的是*副作用。與Haskell中的任何東西都完全相反。 –