Effective C++ item 27 "盡量少做轉型" 提到下列轉型看起來像對的, 實際是錯的:
class SpecialWindow : public Window { public: virtual void onReSize() { static_cast<Window>(*this).onResize(); ... } }
對這點感到很納悶, 於是寫個小程式實驗看看。結果發覺自己沒看清楚, 書上舉例是轉型 Window, 不是轉型 Window*, 所以 Window::onResize() 作用到新產生的物件身上, 結果不同於呼叫 Window::onResize()。
既然已經寫了小程式做實驗, 順便記在這裡供日後備忘。
要點如下:
- 類別 C 的 method 會存取自己的 member field x, 若 C 本身沒有這個 member field, 會往父類別 A 找。
- 承上, A 和 C 的 method 存取到的 x 是同一個 x, 也就是 A::x。
- 若類別 B 宣告和父類別 A 同名稱的 member field x, 則類別 B 和父類別 A 各自擁有一份不同位置的 member field x。
- 承上, A 的 method 會存取 A::x; B 的 method 存取 B::x。呼叫到誰的 method, 就知道改到誰的 x。
題外話, 允許子類別覆寫或重覆宣告同名 method 或 member field 是個糟糕的主意, 再加上可以轉型, 而且轉型後結果還會不一樣, 真是火上加油啊.......。了解 C++ 愈多, 愈覺得要從實作層面才能理解它的語法。
程式碼
範例輸出
$ ./a b.set_x(3) 3 0 copy constructor A is called 3 0 3 30 3 30 c.set_x(3) 3 3 3 3 3 30 3 30 method address &A::set_x 0x4006c8 &B::set_x 0x400710 &C::set_x 0x4007da member field address &b.x 0x7fffb4ef43a4 &((A*)&b)->x 0x7fffb4ef43a0 &c.x 0x7fffb4ef43b0 &((A*)&c)->x 0x7fffb4ef43b0
沒有留言:
張貼留言