PGCafe
Lv 5
PGCafe 發問時間: 電腦與網際網路程式設計 · 8 年前

很畸形?!的type int Data::*有沒有辦法轉型

有一個struct其內容如下

struct Data{

int v1;

char v2;} ; // struct Data

而我宣告了一個變數

int Data::* addr1 = &Data::v1;

char Data::* addr2 = &Data::v2;

這時候

addr1裡面存的是0x00000000

addr2裡面存的是0x00000004

有什麼辦法可以取得這兩個數字並且存到int 變數裡

我試過把他轉成void *或是其他pointer類型都沒辦法

而他也不能做減法,所以沒辦法靠計算得到數字

===========================================

我想做的事實上是類似下面程式碼

template <typename T, typename S>

void FuncA( S T::* addr ){ 取得addr裡的數字做些事情 }

呼叫 : FuncA( &Data::v2 );

有什麼方法可以讓我在FuncA裡面得到addr的數字嗎....

已更新項目:

=====忘記應該用補充內容...把意見移過來這邊========

To 【帕拉提斯】

感謝~這正好是我想要的,在tempalte function裡面去visit指定的member

原來他是有名字的阿!! "pointer to member variable" Google不能搜尋符號真的不好找類似的東西。

pointer to member variable, function不一定是指標的意思是指不同的編譯器可能會做不同的處理,還是在什麼特殊宣告下? 可以的話希望能舉個例

所以理論上是沒辦法取得裡面的數字嗎

2 個已更新項目:

我想再另外問個問題,如果我傳入的不是pointer to member variable而是pointer to member function。

在template function 宣告的部分似乎是都可以接受的,可是如果用d.*addr取值的話似乎要改成(d.*addr)() // 假設沒有參數

那可以判斷傳入的到底是variable還是function嗎? 又或著說可以判斷我應該用哪種方式去如何取值

3 個已更新項目:

=====意見內沒有的新補充======

剛剛發現一個問題是如果member variable 是reference

好像沒辦法用&Data::v3 去pointer他,compiler會說參考成員的指標不合法( VC++2008 )

struct Data{ int &v3; } ;

不過就理論上int a, int &a; 這兩個對於a 這個變數來說不是應該一樣嗎?

差別只在於int a會從memory要一個儲存integer資料的空間,而int &a 則是使用已經有的空間。

意思是除了宣告跟初始化的地方不一樣外,其他地方的行為特性應該相同吧?

4 個已更新項目:

==============================================

To novus

我要的的確是在template下遇到需要offsetof()的問題,而我原本的想法其實是取到值之後,對Data d; 的d去做offset 並且取指定member的值。( 就如同【帕拉提斯】大的回答 )

"最好不要用int存指標,應該要用 ptrdiff_t 或 intptr_t"

收到!! 原先不知道也沒看過有這東西,每次 n大的意見都會讓我學到些東西,謝謝您!!

2 個解答

評分
  • 其威
    Lv 7
    8 年前
    最佳解答

    這個叫做「pointer to member variable」。

    addr1 跟 addr2 內的值是「offset」,意思是說要取得實際的成員變數,必須要用某個物件實體加上該 pointer 的值。

    #include <iostream>

    struct Data {

    int v1;

    char const *v2;

    int v3;

    };

    template <typename T, typename S>

    void FuncA( S T::* addr )

    {

    Data d;

    d.v1 = 123;

    d.v2 = "Hello world!";

    d.v3 = 456;

    std::cout << d.*addr << std::endl;

    }

    int main()

    {

    FuncA( &Data::v1 ); // T = Data, S = int

    FuncA( &Data::v2 ); // T = Data, S = char *

    FuncA( &Data::v3 ); // T = Data, S = int(與第一個相同)

    }

    2012-07-12 23:28:13 補充:

    而且,你舉的例子中 addr1 跟 addr2 也不一定是放 0x00 跟 0x04。

    pointer to member variable 跟 pointer to function 一樣,都不一定是單純的指標。

    他們可能是個特殊的編譯器內部結構,你不能將他們轉成其他東西。

    2012-07-13 22:10:47 補充:

    C++ 不允許宣告 reference to reference、array of references、跟 pointer to reference,因為 reference 不一定會配置儲存空間。

    沒有儲存空間,自然沒有辦法弄個 pointer 指向它。

  • novus
    Lv 6
    8 年前

    我不確定是否真的理解你的問題,好像你的需求類似 offsetof( ),但是在template下遇到問題嗎?

    另外最好不要用int存指標,應該要用 ptrdiff_t 或 intptr_t

    2012-07-13 15:03:46 補充:

    如果是正常操作member,帕拉提斯提供的是最正常的作法。

    我原本以為你要做很tricky的指標運算說。如果要做指標運算的話,應該只有POD是well defined,除此之外的情形最好不要。

    至於 member function 的話,由於機制和一般的 data member 不同,建議獨立實作

    template <typename T, typename S>

    void FuncA( S (T::*fn)() )

    {

    Data d = ...;

    (d.*fn)();

    }

    2012-07-13 15:43:26 補充:

    補充「pointer to member variable, function不一定是指標」:

    這點在普通data member比較不明顯,畢竟 data layout 都可以在編譯期計算,然後表示成某種offset值。(複雜的地方在於遇到繼承時,同一個物件有可能會因為你從不同的觀點看他而有不同的基準位址(this))

    在 function 上就很明顯,例如 virtual function,就必須透過 vptr 和 vtable 才能還原成真實的函數位置。

還有問題?馬上發問,尋求解答。