http://www.dreamincode.net/forums/topic/45816-detail-about-how-vptr-and-virtual-table-works/
and 一兩年前的信
Hi
我昨天在看WebKit的code時 有看到一行怪怪的code
(m_object->*m_function)(this); //請注意 ->*
我本身對c++不熟 但是問了一些熟c++的朋友 他們也不是很清楚
回去看了Stroustup的書 也不是講的很清楚 只有一頁 ( 媽的爛書.....)
不過大概知道這是pointer to member function
pointer to member function 是一個比較少人知道c++特有的feature
不過有整理出一些point出來
1. pointer to member function is NOT pointer to function
void (Test::*pmfn)(void) 跟 void (*pfn)(void) 是不一樣的 即使他們的return type, signature是一樣的
另外也不能把他cast成generic pointer (void *)
可以參考 c++ lite faq的page
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
2. pointer to member function is NOT a pointer to some address
一個pointer to member function , 他只是一個class 中offset的位置而已
( EX: c++ 有個virtual function table的東西 而這pointer to member function只是這table中的offset)
而不是指到Memory中某段的address
另外 他的sizeof 不一定是4(on 32bit), 有些compiler會給他8 byte的length
3. 要dereference pointer to member function 要用 .* or ->*
這也就是我看到那行怪怪code的東西
選 . 跟 -> 的時機就跟C一樣 object 是pointer時就用 ->
然後我寫個test 給大家看看
#include
using namespace std;
class test {
public:
void func();
void func1();
void (test::*pmfn)(); //注意這是個 pointer to member function
// 而且要加test:: ,如果沒有 他就只是一般的pointer to function
// 就是下面那行的 (*pfn)()
void (*pfn)();
void call_pmfn(test&); //這是要用 test::*pmfn 來call function的一個wrapper
};
void test::func()
{
cout<<"test::func\n";
}
void test::func1()
{
cout<<"test::func1\n";
}
void func()
{
cout<<"func\n";
}
void test::call_pmfn(test& t)
{
// (this->*pmfn)(); //這就是call pointer to member function的地方
(t.*pmfn)(); //在這裡我用兩個範例 , both can work
}
int main()
{
test t;
/* pointer to function */
t.pfn = &func; //這裡就是我們一般熟悉的pointer to function
(t.pfn)();
/* general pointer to member function */
void (test::*pmfn1)() = &test::func1; //這裡是一般書上跟網頁上教你如何使用pointer to member function的東西
(t.*pmfn1)(); // 請看待會後面的註解1
/* pointer to member function
* declared inside class, it is also a member of this class */
t.pmfn = &test::func;
//後記20090224 最後發現 (t.*t.pmfn)()也可以
//(t.*pmfn)(); /*error here! 'pmfn' was not declared in this scope*/
//我在上面這行一直遇到compile error 這也是我的朋友們無法回答我問題的地方
// 請看後面的註解2
t.call_pmfn(t);
return 0;
}
註解1
注意這個pmfn1 不是 test裡的member , 即使他有 test::開頭
因為他並沒有declare在test 裡面
其他的 test::func , test::func1可以define在test 外面 是因為他們也有在test 裡面被declared
加了test::開頭 是要告訴compile 這個pointer to member是要指到哪個class裡的member
而compile 在這行 同時也會把test 的refernce傳給這個 pmfn1
(Recall第二點, pointer to member function 並沒有指到memory中的address
所以這時compiler要把class 的資訊告訴 pmfn1)
註解2
如果這裡 pmfn跟 pmfn1一樣用 (t.*pmfn)()的話
是會有compile error出來的
大概原因(大概指的是我沒有很確定 我是從gdb猜的 而不是看gcc的source code)
在這 compile沒有像 給pmfn1一樣 有把test的information給 pmfn
因為compiler在這就把pmfn當作一般的class member一樣
所以當 (t.*pfmn)()時 ,compiler找不到pfmn是哪個class的pointer to member /*這裡就是我不確定的地方*/
so compile will issue a error here
解決的辦法是
member function 跟一般的function有個不一樣的地方
就是他多了一個hidden的parameter , this
所以我作了一個wrapper 的member function
藉由this (也可以傳 test&進來) 的refernce 來call pointer to member function
也就是code裡的 test::call_pmfn()
不過至於pointer to member function什麼時候用
就要參考一些design pattern的書了
與大家分享一下C++特別的地方
thanks
No comments:
Post a Comment