Re: [問題] virtual function 的疑惑2

看板C_and_CPP作者 (我要加入劍道社!)時間15年前 (2010/05/14 02:01), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串4/4 (看更多)
※ 引述《QQ29 (我愛阿蓉)》之銘言: : : 同樣地,compiler 為了達成 dynamic binding,幫你產生了對應的 code: : : struct Bar { : : Foo_vtable* vtable; : 這邊是否筆誤 反正就是 來自Foo::vtable?? : 然後應該會有自己Bar的vtable吧? : VTable *vtable; 這邊的確是我筆誤了 你寫的才是對的 : : void Bar_ctor(Bar* this) // Bar 的建構式 : : { : : Foo_ctor(this); // 它會先呼叫爸爸的建構式 : 呼叫這邊的附加用處 : 是設定 Foo::vtable 去指向Foo的virtual function嗎? 這是「副作用」 呼叫 base class ctor 的目的是初始化 base class member 並不是初始化 vtable : : ... : : ... // 這邊是你寫在 Bar::Bar() 中的東西 : : ... : : this->vtable = bar_vtable; // 這行是 compiler 幫你加的 : 這邊就是設定Bar::vtable了吧 Bar 裡面的 vtable pointer 只有一個 並沒有分 Foo::vtable 或 Bar::vtable : : } : L大舉的例子 : 這麼一來,我們就可以達到 virtual invocation 的效果: : Foo* a; : a = new Foo; : a->g(); // 呼叫的是 Foo::g(),因為在建構式中, : // compiler 幫你把 vtable 指向 foo_vtable : delete a; : a = new Bar; : a->g(); // 同樣的道理,這時候 vtable 指向 bar_vtable : // 所以會呼叫到 Bar::g() : 我再想最後一個a->g()照L大說的可以看成以下 : ( *(a->vtable->g) )(a) //a->g(); : 這時a->vtable 是誰的?? : 我想應該是Foo::vtable吧.... : 這時......Foo::vtable紀錄的是Bar::g()並不是Foo::g() : 表示我上面推論錯了?? 不對 vtable pointer 只有一個 struct Bar { VTable* vtable; int my_data; // Foo::my_data double my_child_data; // Bar::my_child_data }; 這就是 Bar 裡面包含的所有東西 vtable 只有一個 然後它記錄的是 Bar::g() : L大意思是 : Foo_ctor(this);和this->vtable = bar_vtable; 似乎是存取同一個東西 : 才會變成把A::vtable給改了... : 那B本身自己的vtable跑哪了 compiler應該有再偷加東西阿?? 沒有 Bar 裡面只有一個 vtable pointer、自己的成員和 Foo 的成員 沒有 Foo 的 vtable pointer : 完全搞糊塗了 : 若是如果以上沒錯~~ : 假如 : Bar::g(){ Foo::g() <====此時 他是去拿Foo::vtable指到對的table取得g嗎?} 這時候不會去使用 vtable! 因為你很明確地呼叫是 Foo::g() 這個 function 位址在 compile time 就已知了 所以就只是一個正常的 function call 和你呼叫普通的 function 是一樣的 : 這時Foo::g() compiler會轉成什麼去看待的 : ( *(this->Foo::vtable->g) )(this)嗎?? 完全不是這樣 : 可是我實際去稍微的印一下function的位置 : 如下 : http://nopaste.csie.org/5c310 : 1. cout印出的1 我忘記為什麼是印1了 跟 offset有關...可是忘了 因為它們是 virtual function member function pointer to virtual function 記錄的 實際上是該 virtual function 在 vtable 中的 index (這邊的「實際上」其實...是 implementation defined) (因為各家 compiler 實作 member function pointer 的方法都不一樣!) (去用 sizeof 看看 member function pointer 的大小吧) (結果可能出乎你的意料) : 但 printf印出 function位址 卻是相同.... printf 不好,不要用它 (認真) 因為 member function pointer 它的大小是 implementation defined 呀! 在我的系統上 (GCC 4.4 on 64bit Linux) member function pointer 的大小是 16bytes 但是一個普通的 pointer 大小是 8bytes 所以如果照你寫的,在 printf 內,用 %p 印一個指標 它會傻傻地當作每個參數大小都是 8bytes (儘管我傳給它的是兩個 16bytes pointer) 於是印出...第一個 member function pointer 的前 8byte 與後 8byte (真是有夠智障的) : 2. 中斷點 Add Watch 發現 A::XD B::XD位址 怎麼不一樣 印出來卻一樣?? 你為你 watch 到的是真正的 function 位址 但你用 member function pointer 拿到的是 index in vtable 這樣設計的目的 是為了讓 member function pointer 也能多型使用 : 很詭異 : 但如果他們位址一樣 : 那vtable不就記錄的沒用了?? : 還是我印出來的其實是錯的 中斷點的才正確??.....(VC9可斷看A::XD VC8似乎不給看) : 以上 一堆怪問題 : 煩請各位多指教 : 謝謝指點 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.29.108

05/14 15:52, , 1F
謝謝L大 我回家慢慢理解 thx
05/14 15:52, 1F
文章代碼(AID): #1BxAyIOl (C_and_CPP)
文章代碼(AID): #1BxAyIOl (C_and_CPP)