2012-04-27 120 views
9

我已經谷歌搜索和閱讀很多帖子,但有很多不同的答案,所有的邏輯意識,我想知道如果一個專家的專家可以揭開這個問題的神祕面紗。C++構造函數沒有返回類型。究竟是爲什麼?

有人說,沒有回報,因爲沒有辦法返回 - 語法禁止它 - 是的,這是有道理的,但我相信所有的函數都必須返回一些東西,不是嗎? 其他人說,構造函數類返回新創建的對象本身,這似乎有意義,因爲在構造函數中使用賦值運算符。 還有一些人有其他有趣的解釋。

+0

出於好奇,什麼時候它會有用,甚至有意義讓構造函數返回除構造對象之外的其他東西? – kevin628 2012-04-27 18:45:03

+0

AFAIK它返回新創建的對象。 – 2012-04-27 18:45:12

+4

誰說構造函數是一個函數? (除了在「特殊成員函數」的標準部分中描述的事實) – 2012-04-27 18:50:15

回答

12

構造函數不像其他函數那樣調用,所以它們不像其他函數那樣返回。它們作爲某些結構的副作用(演員表,new,可變定義,ctor-initializer-list,按值傳遞,按值返回)。

8

構造函數就地構造,它不需要返回任何東西。

我相信,所有功能都返回的東西

void

+0

構造函數甚至不返回'void'(如果有意義的話)。他們沒有返回類型。 – 2012-04-27 18:49:18

+1

@DavidHammen這只是語法上的區別。聲明一個函數的返回類型爲'void'具有相同的含義。 – bames53 2012-04-27 18:55:29

+0

它只是語法上的差異嗎?構造函數是一個void函數,因爲return語句在構造函數中必須是'return;'。但是,通過使構造函數不可調用並且未指定返回類型,該標準似乎允許編譯器供應商使構造函數返回某些東西,只要它返回void即可。 – 2012-04-27 19:06:35

1

構造函數缺少返回類型 - 甚至沒有 void - 意味着您無法從C++代碼中調用構造函數。這就是要點。調用構造函數沒有任何意義。調用構造函數是非法的,消除了這類用戶錯誤的可能性。

編輯

巴恩斯是正確的,你不能調用構造函數的最終原因是,他們沒有名字。 (即使是這種忽略,你可以間接調用構造函數通過放置新的。)

再次嘗試:

你不能從你的C調用構造函數++代碼,因爲構造函數沒有名稱。使構造函數不具有返回類型,強調程序員構造函數是一種非常不同於其他函數的函數。如果構造函數返回任何東西,實際返回的是什麼,取決於供應商。

+0

構造函數不返回任何東西與您是否可以調用構造函數無關。您不能調用構造函數,因爲構造函數沒有名稱,並且沒有調用它的語法。 (只有解決方法;展示位置新)。 – bames53 2012-04-27 18:49:55

10

構造函數沒有指定返回類型,因爲它會是多餘的:除構造函數可能「返回」的構造函數外,沒有其他類型。我將「return」放在引號中,因爲技術上的構造函數不會返回任何東西:當它們在靜態上下文中被調用時,它們會初始化一個實例;當它們在動態上下文中被調用時,它是運算符new返回的內容,而不是構造函數。

+2

和*看起來像一個構造函數調用的事實際上是一個強制轉換。 – 2012-04-27 18:53:25

+2

@downvoter請解釋你們的選票 – dasblinkenlight 2012-04-28 12:50:12

1

但我相信所有的函數都必須返回一些東西,不是嗎?

不是。從函數返回值是什麼意思?那麼,實現的ABI將指定對於某些返回類型,函數會將某些寄存器或某些存儲器設置爲與堆棧指針相距一定的偏移量,然後將該函數返回的值設置爲該值。

很明顯,寄存器和內存存在並且在調用構造函數或void函數後包含數據,但是該語言表示這些函數不會返回任何內容,因此ABI沒有指定要查找哪些寄存器或內存以查找一個返回值。代碼無法設置返回值,調用代碼可以獲得任何返回值。

所以不,函數不必返回任何東西。

2

假設構造函數可以返回的東西,那麼這對於下面的函數調用問題的影響:

class Object{ 
    public: 
     bool Object(){ ... }; 
     ... 
}  

SomeFun(Object obj){ ... } 

SomeFun(Object()); 
// Ha! SomeFun jokes on an error about a non-Object argument(of type bool), returned 
// by the anonymous temporary Object() 

從返回防止構造函數,方便使用匿名臨時對象,還有更多的C++功能一起。如果沒有這樣的規則,無害的語句可以變得模棱兩可:

Object obj(Object()); 
// How does the variable obj decide which constructor to call, 
// based on its argument type? 
// 
// Does it call: bool Object::Object(Object&) or 
//     Object::Object(bool)(if it exists)? 

返回一個值的能力構造函數,創建對象的複雜化 - 具有單一明確的類型,類名,在沒有任意返回值,避免了這樣的問題。

讀者可以提出更多的例子,C++習語被缺少這樣的規則所阻礙嗎?

+0

這種說法讓我們相信,一個構造函數返回的任意值將是可取的,如果它不擦等地建立了語言功能走錯了路......相反,一個構造函數是特殊用途的功能[使用初始化它的類的對象](http://www2.research.att.com/~bs/glossary.html#Gconstructor)...重新在這個角度回答你的答案... – user1055604 2012-04-28 06:25:16

0

構造函數隱式返回類本身的一個實例。如果它被設計爲返回一些東西並且程序員返回了與類本身完全不同的東西,那將是矛盾的。基本上,語法會令人困惑。

1

構造函數可能是一個壞名字。它實際上是預構建對象的初始化工具。說明這一點最簡單的方法是不使用C++構造函數的等效構造的僞示例。

隨着構造

struct X { 
    int a; 
    X() { 
     a = -5; 
    } 
}; 

int main() { 
    X* x1 = new X(); // X created as a "reference object". 
    X x2;   // X created as a "value object" on the stack. 
    return x1->a - x2.a; 
} 

沒有構造函數現在

struct X { 
    int a; 
    void initialize() { 
     a = -5; 
    } 
    static X* create() { 
     X* res = (X*)malloc(sizeof(X)); 
     res->initialize(); 
     return res; 
    } 
}; 

int main() { 
    X* x1 = X::create(); // New constructed heap-allocated X 
    X x2;    // Stack-allocated X 
    x2.initialize();  // Manually initialized 
    return x1->a - x2.a; 
} 

,如果你想象X::initialize在第二個例子是要進行退貨,說bool指示成功或失敗,你會有一個問題。在main()中,不注意的程序員可能會以X未正確初始化,導致未定義的行爲(通常是在生產之前可能未發現的難以調試的崩潰)。

這是構造函數特殊化的核心原因之一。退出構造函數的唯一兩種方式是通過正常完成或通過異常,然後由調用方處理(或傳遞到堆棧上),然後由必須。在任何情況下,您都會阻止以未初始化的對象結束。

作爲一個側面提示,未初始化的對象是C中更常見的錯誤原因之一,它沒有任何東西可以幫助程序員這樣做。