2011-02-28 174 views
1

如果我有兩個類與同一名稱和類型的成員在同一層次結構中,那麼創建指向基類變量的成員指針的「正確」方法是什麼?例如,C++指向成員的指針

class A 
{ 
    int x; 
    A():x(1){} 
}; 
class B : public A 
{ 
    int x; 
    B():x(2){} 
}; 
int main(int argc, char *argv[]) { 
    B classB; 
    int B::*ptr = &B::x; 
    int B::*ptr1 = &B::A::x; 
    int A::*ptr2 = &A::x; 
    printf("%d,%d,%d\n", classB.*ptr, classB.*ptr1, classB.*ptr2); 
    return 0; 
} 

在我的編譯器(LLVM GCC)上,它會打印2,1,1,就像我期望的那樣。這引出了我的兩個問題。

  1. 當涉及到C++標準時,上述所有三個實現都是「安全的」嗎?

  2. 如果是這樣,是否有任何主流編譯器與其中任何一個不兼容?

+0

你爲什麼不離開B班? 你能解釋爲什麼你需要int x在A類和B類? – santiagoIT 2011-02-28 03:31:25

+1

上面是一個簡化的例子,但這是一個序列化/反射系統,我必須確保它將保留爲任何類型的層次結構,並將其傳遞給它。 – 2011-02-28 03:37:48

回答

2

相信三者都是安全的,雖然我不能對他們的標準引用章節和詩句。 :)

這就是說,我已經運行了老版本的Visual Studio中的成員函數指針中的一個非常具體的錯誤(我不記得是哪個,我很害怕)。具體來說,我有這樣的結構:

struct optable_entry { 
    const char *name; 
    void (*MyClass::run)(); 
}; 

const optable_entry operations[] = { 
    { "foo", &MyClass::foo }, 
    /* ... */ 
}; 

有了這個,由於某種原因,成員函數值將不會正確初始化。在我的情況下,這是生成的代碼,所以用一個大規模的switch語句代替它並不是太麻煩,但是需要注意的是 - 成員函數指針很少被使用,這樣怪異的角落案例可能會潛伏在你的編譯器中。