因為一些因素,讓我學習到一段程式碼,這段程式碼就是這篇主題的主角,意圖使人出錯的程式碼。
這段code的規格是
初始化玩遊戲後,確保有一個使用者在遊戲裡面,所以要在init結束前呼叫join。
至於規格為什麼要這樣設計,不要問我XD
原本的code是python的。我把python的code轉成用c++來表達,所以function前面都會有virtual,以符合python情形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class = "com" >#include</span><span class = "pln" > </span><span class = "str" ><cstdio></span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > main</span><span class = "pun" >(){</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pln" > father</span><span class = "pun" >;</span><span class = "pln" > father</span><span class = "pun" >.</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span> |
坦白講,這段程式碼看起來還好。除了一個function做兩件事情外。也沒什麼。執行順序也如我們的預期
father init start father init end father join start father join end
可是如果他是基底類別。會有子類別繼承他
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <span class = "com" >#include</span><span class = "pln" > </span><span class = "str" ><cstdio></span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pun" >:</span><span class = "kwd" > public </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child init start\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > ret </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "com" > // do something It need.</span><span class="pln"> printf </span><span class = "pun" >(</span><span class = "str" > "child init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > ret</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join start\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > main</span><span class = "pun" >(){</span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pln" > child</span><span class = "pun" >;</span><span class = "pln" > child</span><span class = "pun" >.</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span> |
程式碼看起來還好,只是執行解果有點詭異。恩....子類別join發生在子類別init完成前。
child init start father init start father init end child join start father join start father join end child join end child init end
假設你不care這情形,過了一段時間,你突然想新增一些東西像這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class = "com" >#include</span><span class = "pln" > </span><span class = "str" ><cstdio></span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pun" >:</span><span class = "kwd" > public </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > special</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child init start\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > ret </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > special </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "com" > // do something It need.</span><span class="pln"> printf </span><span class = "pun" >(</span><span class = "str" > "child init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > ret</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join start\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "special = %d\n" </span><span class = "pun" >,</span><span class = "pln" > special</span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > main</span><span class = "pun" >(){</span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pln" > child</span><span class = "pun" >;</span><span class = "pln" > child</span><span class = "pun" >.</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span> |
你在子類別新增一個變數,初始化時需要給他一個值,子類別的join的時候會需要他。你會發現這樣寫,special的值不合你預期(廢話,因為join發生在special = 1之前)。
怎麼辦,把special = 1移到Father::init前面就好了。 恩....
問題好像解決了,也沒什麼呀
有一天,父類別要做一些更動,要多加一個屬性name,父類別的name是從1開始算,子類別的name是從2開始算。
像這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <span class = "com" >#include</span><span class = "pln" > </span><span class = "str" ><cstdio></span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > name</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init start\n" </span><span class = "pun" >);</span><span class = "pln" > name </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "name = %d\n" </span><span class = "pun" >,</span><span class = "pln" > name</span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pun" >:</span><span class = "kwd" > public </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > special</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child init start\n" </span><span class = "pun" >);</span><span class = "pln" > name </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >2</span><span class = "pun" >;</span><span class = "pln" > special </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > ret </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "com" > // do something It need.</span><span class="pln"> printf </span><span class = "pun" >(</span><span class = "str" > "child init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > ret</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join start\n" </span><span class = "pun" >);</span><span class = "pln" > name </span><span class = "pun" >+=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "special = %d\n" </span><span class = "pun" >,</span><span class = "pln" > special</span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > main</span><span class = "pun" >(){</span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pln" > child</span><span class = "pun" >;</span><span class = "pln" > child</span><span class = "pun" >.</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span> |
1 |
你會發現,印出來的 name 值會是父類別的值再加一,而不是子類別的值再加一。怎麼辦?
在join那邊初始化?
不行,join在那邊會被呼叫很多次,所以在join初始化會一直讓那個變數被初始化
所以不能在那初始化。
所以怎麼辦?
不要呼叫父類別的函數好了,把父類別的函數程式碼直接複製到子類別好了
很好,問題解決了,只是這樣幹嘛用繼承呢?
如果你哪天父類別的init改了,恭喜你。你要把父類別的code重新複製到子類別去。
每改一次,複製一次 ...
不小心改錯,你的code就gg了。
有人會說,我就是要初始化完呼叫,那該怎麼辦呢?
事實上也不難。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <span class = "com" >#include</span><span class = "pln" > </span><span class = "str" ><cstdio></span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > name</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init start\n" </span><span class = "pun" >);</span><span class = "pln" > name </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join start\n" </span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "name = %d\n" </span><span class = "pun" >,</span><span class = "pln" > name</span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "father join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init_and_join</span><span class = "pun" >(){</span><span class = "pln" > </span><span class = "com" > //the functino can't be overrided.</span><span class="pln"> init</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > class </span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pun" >:</span><span class = "kwd" > public </span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >{</span><span class = "pln" > </span><span class = "kwd" > public </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > special</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > init</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child init start\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > ret </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "pln" >init</span><span class = "pun" >();</span><span class = "pln" > name </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >2</span><span class = "pun" >;</span><span class = "pln" > special </span><span class = "pun" >=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "com" > // do something It need.</span><span class="pln"> printf </span><span class = "pun" >(</span><span class = "str" > "child init end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "kwd" > return </span><span class = "pln" > ret</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "kwd" > virtual </span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > </span><span class = "kwd" >join</span><span class = "pun" >(){</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join start\n" </span><span class = "pun" >);</span><span class = "pln" > name </span><span class = "pun" >+=</span><span class = "pln" > </span><span class = "lit" >1</span><span class = "pun" >;</span><span class = "pln" > </span><span class = "typ" >Father</span><span class = "pun" >::</span><span class = "kwd" >join</span><span class = "pun" >();</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "special = %d\n" </span><span class = "pun" >,</span><span class = "pln" > special</span><span class = "pun" >);</span><span class = "pln" > printf </span><span class = "pun" >(</span><span class = "str" > "child join end\n" </span><span class = "pun" >);</span><span class = "pln" > </span><span class = "pun" >}</span><span class = "pln" > </span><span class = "pun" >};</span><span class = "pln" > </span><span class = "kwd" > int </span><span class = "pln" > main</span><span class = "pun" >(){</span><span class = "pln" > </span><span class = "typ" >Child</span><span class = "pln" > child</span><span class = "pun" >;</span><span class = "pln" > child</span><span class = "pun" >.</span><span class = "pln" >init_and_join</span><span class = "pun" >();</span><span class = "pln" > </span><span class = "pun" >}</span> |
這樣問題就解決了,我們只要呼叫initandjoin()就可以了。他會幫我們完成初始化和join的動作。如果你在寫java,你還可以再initandjoin()前面加個final,防止子類別override,導致行為改變。
Sometimes sex toys can even have sex toy store medical makes use of if you have a sexual dysfunction or medical condition. There are many different types of|several varieties of|various sorts of} sex toys, different people|and folks} use them tons of|for lots of|for many} completely different reasons. We actually have a dildo with a suction cup for unmatched pleasure wherever may be}. Compared to other sex toys in the marketplace, utilizing a dildo might be preferable. Unlike some sex toys, asilicone dildo has a firm but flexible design.
回覆刪除