大家都知道在c++中我們一般在構造函數中為對象配置設定記憶體空間然後初始化成員變量,比如我們調用了new某個東西,那麼在堆上會先為對象配置設定記憶體空間,然後調用構造函數,在構造函數中完成一些初始化的工作。而二段構模組化式就是将記憶體空間的配置設定和初始化分開來完成,然後調用一個靜态方法來傳回這個對象。就拿cocos2dx中的sprite類來說吧,當我們調用sprite::create()的時候内部先使用new來配置設定記憶體空間,然後調用init方法來初始化一些變量的設定。是以cocos2dx中的二段構模組化式就是将new配置設定記憶體空間和init初始化内容分開來處理,而不是c++傳統的做法在構造函數中初始化變量。
<code>1</code>
<code>sprite* sprite::create()</code>
<code>2</code>
<code> </code><code>{</code>
<code>3</code>
<code> </code><code>//配置設定記憶體</code>
<code>4</code>
<code> </code><code>sprite *sprite = </code><code>new</code> <code>sprite();</code>
<code>5</code>
<code> </code><code>//init初始化</code>
<code>6</code>
<code> </code><code>if</code> <code>(sprite && sprite->init())</code>
<code>7</code>
<code> </code><code>{</code>
<code>8</code>
<code> </code><code>//記憶體管理的工作</code>
<code>9</code>
<code> </code><code>sprite->autorelease();</code>
<code>10</code>
<code> </code><code>return</code> <code>sprite;</code>
<code>11</code>
<code> </code><code>}</code>
<code>12</code>
<code> </code><code>cc_safe_delete(sprite);</code>
<code>13</code>
<code> </code><code>return</code> <code>nullptr;</code>
<code>14</code>
<code> </code><code>}</code>
上邊就是使用二段構模組化式的過程,sprite首先調用new來配置設定記憶體空間,然後調用init函數來完成初始化的工作,順帶還做了記憶體管理的工作,最後傳回初始化好的對象。是以看了sprite的create方法的實作,我們也知道了應該怎麼使用這個二段構模組化式了吧。
第二個問題是為什麼要這麼用,對于c++程式員來說初始化工作不都是在構造函數中完成的嗎,cocos中為何要這麼做呢?這裡引述一下王哲的話:“其實我們設計二段構造時首先考慮其優勢而非相容cocos2d-iphone. 初始化時會遇到圖檔資源不存在等異常,而c++構造函數無傳回值,隻能用try-catch來處理異常,啟用try-catch會使編譯後二進制檔案大不少,故需要init傳回bool值。symbian, bada sdk,objc的alloc + init也都是二階段構造”。現在大家明白了吧,相容cocos2d-iphone是一個原因,另一個重要的原因是構造函數沒有傳回值啊,如果加載資源圖檔的時候不存在怎麼辦,是以初始化的工作寫在init函數中,這個函數傳回的bool值用來判斷是否初始化成功。使用這種方法還可以強化設計,想想自己寫代碼的時候是不是因為沒有初始化某個成員變量導緻了bug,這樣做就是提醒你記得要在init中初始化成員變量。通過create靜态函數傳回的這個對象也實作了cocos2dx中的記憶體管理,就不用我們自己麻煩了。還有一個原因是在c++的構造函數中是不能調用虛函數的,為了調用虛函數來完成一些功能就要寫在init函數中。
以上就是二段構模組化式的說明了,在我們寫cocos程式的時候其實不知不覺就已經在使用這個構模組化式了,想一下我們一個類繼承了layer,然後使用了宏create_func(),這不就是create靜态方法嗎,在init函數中完成了初始化,整個過程就是在用這種設計模式!