我觉得这两个功能属于重合了啊,都是在类调用的时候进行初始化
class T
{
public:
int a;
int b;
T();
virtual ~T();
void init();
}
T::T()
{
a = 1;
b = 2
}
void T::init()
{
a = 3;
b = 4;
}
为毛要有这种设定
大家讲道理2017-04-17 11:42:00
C++ 只規定了構造函數,init()
是用 C++ 的人自己覺得合適才需要聲明的,並不是說每個 C++ 類別都需要有個 init()
才行。
一般來說,建構函式應該只用於初始化成員變量,而額外的初始化函式應該用來做業務邏輯相關的初始化,特別是包含了錯誤分支的業務碼。
這樣規定是因為建構函式有很多限制,例如它既不能回傳錯誤碼表示錯誤,又不應該拋出例外(因為這樣做會導致析構函式不執行,往往會造成問題),所以當業務邏輯裡面存在可能失敗的邏輯的時候,建構函式就無法勝任,必須再寫一個單獨的初始化函式來完成這些事情。
在題目中所舉的例子其實是一種誤用,a
/b
作為成員變數理應在構造函數裡面初始化,init
如果再去初始化一次就毫無道理了,有些畫蛇添足。而且建構子寫成下面這種最好:
T::T()
: a(1)
, b(2)
{}
巴扎黑2017-04-17 11:42:00
我不知道你這個類別是自己設計出來為了說明問題還是從生產程式碼抽象化出來的。
這裡我想說的問題是,RAII跟物件的兩步驟構造。
中文我就不翻譯了。
這個在c++世界中應該是經常被提及的一個術語。
主要說的就是,當物件創建完成時,它所需的所有資源也都已經獲得。
這個對棧上創建的物件非常有用,不需要額外的處理,物件就可以得到合適的構造;並且在物件離開它的scope時,它所獲得的資源被很自然的釋放。當然它要求,類別的建構子還有析構函數要好好的寫。
當然,如果你有很多地方需要在堆疊上建構對象,那麼shared_ptr是少不了的。
這是我給它的名字(不知道正式的名字叫啥),很多時候,這樣做,也是c++中的無奈之舉。
比如說,這個類別在建構的時候需要創建一個資料庫連結(什麼?你不會自己找麻煩吧)。你應該知道,在c++的建構子裡面處理一些錯誤/異常,是多麼痛苦的事。這時候,把這些比較繁瑣的,容易出現錯誤的東西拉出來,放到init函數中,是比較好的處理方法。你對init函數做錯誤處理也來得方便些,同時也不影響整個程式的語意。試想下,一個物件在建構函式中掛掉,你該如何對這個物件做回收呢?還是來個init函數把。
有了init,對應的,你應該做一個類似destroy的函數出來,放到析構函數裡面還是讓呼叫者自己調用,你可以自己決定。但個人認為,還是讓用戶自己調比較好,萬一destroy的過程出現錯誤了呢?
黄舟2017-04-17 11:42:00
cpp物件定義的時候就必須初始化,不夠靈活。用動態分配的話又可能忘了釋放。不像java。
所以有時候構造器只是給各字段賦預設值,init才是真正的初始化,需要的時候手動呼叫。回收的工作由析構器來管。
不過現在不必那麼糾結了,用shared_ptr吧。