<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 對象的回歸 先擺出?`create_chain_node`?函數: ~~~ struct chain_node * create_chain_node(void) { struct pair *left_hole = pair(pair_for_double_type(1.0, 1.0), malloc_double(0.5)); struct pair *right_hole = pair(pair_for_double_type(9.0, 1.0), malloc_double(0.5)); struct pair *holes = pair(left_hole, right_hole); struct pair *body = pair_for_double_type(10.0, 1.0); struct pair *shape = pair(body, holes); struct chain_node *ret = malloc(sizeof(struct chain_node)); ret->prev = NULL; ret->next = NULL; ret->shape = shape; return ret; } ~~~ `create_chain_node`?函數可以創建鏈節,它是借助很抽象的?`pair`?結構體將很多種類型的數據層層封裝到了?`chain+node`結構體中,那么我們如何從?`chain_node`?結構體中提取這些數據,并使之重現它們所模擬的現實事物? 例如,我們怎樣從?`chain_node`?結構體中獲取一個?`left_hole`?的信息?顯然,下面的代碼 ~~~ struct *t = create_chain_node(); struct pair *shape = t->shape; struct pair *holes = shape->second; struct pair *left_hole = holes->first; ~~~ 并不能解決我們的問題,因為?`left_hole`?中只是兩個?`void *`?指針,而我們需要知道的是?`left_hole`?的中心與半徑。那么我們繼續: ~~~ struct pair *center = left_hole->first; double radius = *((double *)(left_hole->second)); ~~~ 依然沒有解決我們的問題,因為我們想要的是?`left_hole`?的中心,而不是一個包含著兩個?`void *`?指針的?`center`,所以需要繼續: ~~~ double center_x = *((double *)(center->first)); double center_y = *((double *)(center->second)); ~~~ 最后我們得到了三個?`double`?類型的數據,即?`center_x`,?`center_y`,?`radius`,于是似乎我們的任務完成了,但是你如何將上述過程寫成一個函數?`get_left_hole`? C 語言中的函數只能有一個返回值。如果通過函數的參數來返回一些值,那么`get_left_hole`?是能寫出來的,例如: ~~~ void get_left_hole(struct chain_node *t, double *x, double *y, double *r) { struct pair *shape = t->shape; struct pair *holes = shape->second; struct pair *left_hole = holes->first; struct pair *center = left_hole->first; *x = *((double *)(center->first)); *y = *((double *)(center->second)); *r = *((double *)(left_hole->second)); } ~~~ 但是,如果你真的這么寫了,那只能說明再好的編程語言也無法挽救你的品味。 我們應該繼續挖掘指針的功能,像下面這樣定義?`get_left_hole`會更好一些: ~~~ struct point { double *x; double *y; }; struct hole { struct point *center; double *radius; }; struct hole * get_left_hole(struct chain_node *t) { struct pair *shape = t->shape; struct pair *holes = shape->second; return holes->first; } ~~~ 好在哪?我們充分利用了 C 編譯器對數據類型的隱式轉換,這實際上就是 C 編譯器的一種編譯期計算。這樣做可以避免在代碼中出現?`*((double *)(...))`?這樣的代碼。`void *`?指針總是能通過賦值語句自動轉換為左值的,前提是你需要保證左值的類型就是?`void *`?的原有類型。這是 C 語言的一條清規戒律,不能遵守這條戒律的程序猿,也許再好的編程語言也無法挽救他。 C++ 這個叛徒,所以無論它有多么強大,也無法拯救那些無法保證左值的類型就是?`void *`?原有類型的程序猿。用 C++ 編譯器迫使程序猿必須將 ~~~ struct pair *shape = t->shape; struct pair *holes = shape->second; ~~~ 寫成: ~~~ struct pair *shape = (struct pair *)(t->shape); struct pair *holes = (struct pair *)(shape->second); ~~~ 否則代碼就無法通過編譯。這樣做,除了讓代碼更加混亂之外,依然無法挽救那些無法保證左值的類型就是?`void *`?原有類型的程序猿,只會讓他們對裸指針以及類型轉換這些事非常畏懼,逐漸就走上了惟類型安全的形而上學的道路。C++ 11 帶來了新的智能指針以及右值引用,希望他們能得到這些新 C++ 式的拯救吧。 當我們用面向對象的思路實現了?`get_left_hole`?之后,就可以像下面這樣使用它: ~~~ struct *t = create_chain_node(); struct hole *left_hole = get_left_hole(t); printf("%lf, %lf, %lf\n", *(left_hole->center->x), *(left_hole->center->y), *(left_hole->radius)); ~~~ 一切都建立在指針上了,只是在最后要輸出數據的需用?`*`?對指針進行解引用。 上述代碼中有個特點,`left_hole`?并不占用內存,它僅僅是對?`t`?所引用的內存空間的再度引用。可能有人會擔心`left_hole`?具有直接訪問?`t`?所引用的內存空間的能力是非常危險的……有什么危險呢?你只需要清楚?`left_hole`?只是對其他空間的引用,而這一點自從你用了指針之后就已經建立了這樣的直覺了,你想修改?`left_hole`?所引用的內存空間中的數據,就可以 do it,不想修改就不去 do it,這有何難?如果自己并不打算去修改?`left_hole`?所引用的內存空間中的數據,但是又擔心自己或他人會因為失誤而修改了這些數據……你應該將這些擔心寫到?`get_left_hole`?的注釋里! 對于只需要稍加注意就可以很大程度上避免掉的事,非要從編程語言的語法層面來避免,這真的是小題大作了。如果我們在編程中對于?`void *`?指針的隱式類型正確轉換率高達 99%,為何要為 1% 的失誤而修改編程語言,使之充滿各種巧妙迂回的技巧并使得代碼愈加晦澀難懂呢? 《C 陷阱與缺陷》的作者給出了一個很好的比喻,在烹飪時,你用菜刀的時候是否失手切傷過自己的手?怎樣改進菜刀讓它在使用中更安全?你是否愿意使用這樣一把經過改良的菜刀?作者給出的答案是:我們很容易想到辦法讓一個工具更安全,代價是原來簡單的工具現在要變得復雜一些。食品加工機一般有連鎖裝置,可以保護使用者的手指不會受傷。然而菜刀卻不同,如果給菜刀這種簡單、靈活的工具安裝可以保護手指的裝置,只能讓它失去簡單性與靈活性。實際上,這樣做得到的結果也許是一臺食品加工機,而不再是一把菜刀。 我成功的將本節的題目歪到了指針上。現在再歪回來,我們來談談對象。其實已經沒什么好談的了,`get_left_hole`?返回的是泛型指針的類型具化,借助這種類型具化的指針我們可以有效避免對?`pair`?中的?`void *`?指針進行類型轉換的繁瑣過程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看