2011-09-12 13 views
2

我正在重構一些舊的C風格的代碼,以使其更符合C++代碼。我仍然是一個有點新的C++構造函數應該如何報錯?指向外部標誌?

我的工作代碼的一個例子是如下

Errmsg foo{ 
    ErrMsg err = NoError; 
    /* 
    Some Processing 
    */ 
    err = foo_cleanup(err,/* some parameters*/); 
    /* 
    Some More Processing 
    */ 
    return err; 
} 

我想開發一個類的,這樣

class foo_class 
{ 
public: 
    foo_class(Errmsg errmsg_init&,/*Some other arguments */): 
     errmsg(&errmsg_init), 
     /*Initialize other parameters */{} 

    void foo_cleanup (/*Other parameters*/); 
    // same functionality, but since the source variable is available, 
    // it can be modified without having to return any variable 

    ~foo_class(){foo_cleanup(/*Parameters*/);} 

    /* 
    Member functions 
    */ 

private: 
    Errmsg* errmsg; 
    /*Some other parameters */ 
}; 

Errmsg foo{ 
    ErrMsg err = NoError; 
    foo_class foo_obj(err); 
    /* 
    Some Processing 
    */ 

    // The class would be 
    //cleaned up before returning 
    // and the err variable would be 
    //modified in the destructor 
    return err; 
} 

雖然我有能夠使用類似於這種方法的東西,我不知道這是否便攜。

這是正確的做法嗎?

如果不是,我只是使用指針來初始化類,而不是通過引用傳遞錯誤消息變量?或者還有什麼我可以做的嗎?

我不能在當前階段使用異常,因爲有很多來自外部代碼的函數調用仍然使用「返回錯誤消息」方法。

回答

1

暫且不說,你應儘量修復調用代碼,這樣的例外是OK,你可以使用兩階段構造:

struct foo_class { 
    foo_class() { } // default constructor cannot fail 
    Errmsg nothrow_init(/* other params */) throw() { 
     /* initialize other parameters */ 
    } 
    foo_class(/* other params */) { 
     if (nothrow_init(/* other params */) != ERRMSG_OK) { 
      throw something; 
     } 
    } 
}; 

現在,使用異常的代碼可以調用多arg構造函數(並使對象處於可用狀態),而異常代碼可以調用默認構造函數,然後調用nothrow_init(並且事實上,如果nothrow_init失敗,則它們手中有不可用的對象,並且他們有責任確保他們不使用它)。在將來,當您將代碼庫的其他部分引入異常使用狀態時,您會發現init中的代碼會調用本身可能拋出的東西。此時,您可以開始移動代碼,以便nothrow_init可以調用可引發的函數,但會捕獲任何異常並將其轉換爲錯誤代碼。假設它是一個內部類,那麼最終什麼都不會使用nothrow_init,你可以刪除它。

0

,因爲有很多 函數調用/從使用「返回錯誤 消息」的方式還是外部代碼,我不能在現階段使用異常。

然後先解決這個問題。然後使用例外。

+0

-1因爲......這麼多東西。例外是一個工具。無視所有事情,並抨擊你的信念,你應該如何編程是另一回事。一個句子回覆很少有用。作爲控制流的例外?等..請擴展你的推理,我會投票並說我錯了。 – 2011-09-12 18:00:59

+0

看到我的答案和鏈接的GOTW。例外情況不適用於所有情況,但對於那些情況而言,有***無***有效替代品。失敗的對象構造就是其中之一。 – spraff

+0

如何不在流控制更適合的構造函數中進行操作。有時在這裏做這些事情是完全有效的。這顯然不是這種情況。真的,如果有機會,你們會拋出CHeyWeJustAddedANumberException:P – 2011-09-13 03:57:43

1

你的代碼是危險的,因爲它允許不好用,這樣的情況下:

return new FooClass (local_error_code_variable); 

不要試圖返回代碼信號構造失敗。 你不能。使用例外。

您可以在返回代碼中包裝異常,反之亦然。

class NewAPIClass { 
    NewAPIClass() { 
     error_code err = old_api_function(); 
     if (OLD_API_OK != err) 
      throw NewAPIException (err); 
    } 
} 

extern "C" error_code new_api_callback_function (argument arg) { 
    try { 
     NewAPIClass object; 
     object .do_work(); 
    } 
    catch (...) { 
     return OLD_API_ERROR; 
    } 
} 

int main() { 
    old_api_install_callback (new_api_callback_function); 
} 

例外很重要。有很多很好的GOTW articles,你應該理解他們作爲一個C++開發人員的目標。

編寫新代碼以正確使用例外。只要您碰到舊代碼和新代碼之間的邊界,就轉換錯誤類型。

順便說一句,異常是解決構造函數失敗只有合理的方式。它是RAII的一部分,這是使C++如此強大的關鍵。構造函數建立你的不變量和異常信號表示不滿足後置條件 - 把它放在一起,這裏是重要的哲學:在C++中只有有效的對象應該存在,如果你通過利用RAII得到這個權利,一個對象就是該程序有效性的證明。

相關問題