1

同じ階層に同じ名前とタイプのメンバーを持つ2つのクラスがある場合、基本クラスの変数へのメンバーポインターを作成する「正しい」方法は何ですか。元。

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を出力します。これは私の2つの質問につながります。

  1. C ++標準に関しては、上記の3つの実装すべてが「安全」ですか?

  2. もしそうなら、主流のコンパイラはこれらのいずれかと非互換性がありますか?

4

1 に答える 1

2

私はそれらの標準から章と詩を引用することはできませんが、3つすべてが安全であると信じています。:)

そうは言っても、古いバージョンのVisual Studioのメンバー関数ポインターに非常に特殊なバグが1つあります(どちらかは覚えていませんが、恐れています)。具体的には、次のような構造になっています。

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

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

これにより、何らかの理由で、メンバー関数の値が適切に初期化されませんでした。私の場合、これは生成されたコードなので、代わりに大規模なswitchステートメントに置き換えるのはそれほど問題ではありませんでしたが、注意が必要です-メンバー関数ポインターが十分に使用されることはめったにないため、このような奇妙なコーナーケースが発生する可能性がありますコンパイラに潜んでいます。

于 2011-02-28T03:38:02.740 に答える