2016-09-02 14 views
-1
struct Base1 { 
    int value1; 
    Base1() : value1(1) {} 
}; 

struct Base2 { 
    int value2; 
    Base2() : value2(2) {} 
}; 

struct Derived : public Base1, public Base2 {}; 

void func(int Derived::*pmf, Derived *d) 
{ 
    printf("%d\n", d->*pmf); 
} 

void func2() 
{ 
    Derived d; 
    int Base2::*b = &Base2::value2; 
    func(b, &d); 
} 

int main() 
{ 
    func2(); 
} 

Output is 2 

こんにちは皆さん。 私はInside the c++ object modelという本を読んでいます。メンバーデータの章へのポインタです。ピクチャには、第2の基本クラスのデータメンバへのポインタが関数に渡され、派生クラスのメンバへのポインタを要求するコードがあります。私はその場で何が起こっているのか本当に分かりません。このような変換は、特に明示的なキャストが使われていない限り、クラスへのポインタの観点から考えると、そういったことは許されませんが、コンパイラが渡されたポインタを調整すると言われています関数に渡す。 私の2つの質問は次のとおりです:メンバーデータ変換のポインター

1)この状況で何が起こっているのですか?

2)コンパイラがポインタを調整するだけの場合は、コンパイラがポインタの型を常に知っているか、実行時までポインタ型がわからないときはいつもありますか?

更新:コードを修正し、初期値をvalue1とvalue2に追加しました。 func2()の呼び出し後、出力は '2'になります。これはBase2 :: value2なので、明らかにコンパイラはポインタを調整しました。

+1

コードを画像ではなくプレーンテキストとして送信します。 – Barmar

+0

私は何かが間違っていると思う、ちょうどそのコードがあまり意味をなさない。 –

+0

編集された質問。画像をコードに置き換えました。 –

答えて

2

背後では、コンパイラは、データオブジェクトへのポインタを整数オブジェクトとしてクラスオブジェクトに格納します。 (私は簡単のために仮想基底クラスを無視しています。)

val2Base2の開始時であるので、だから、ラインint Base2::*bmp = &Base2::val2;は、ゼロに番号を初期化するようなボンネットの下に見えます。

あなたはfuncbmpを渡すと、コンパイラが暗黙的にタイプint Derived::*にタイプint Base2::*から変換されます。 Base2のメンバーであるものもDerivedのメンバーであるため、これは許可され、安全です。しかしBase2サブオブジェクトDerivedは(おそらく)Derivedの先頭にないので、この変換を行うときにオフセットを変更する必要があります。 Base2サブオブジェクトがDerivedオブジェクトに4バイトを開始すると仮定すると、フード下での動作はfuncに渡されるときにbmpに4を追加するように見えます。

すべてfuncは、dというポインタで表されるアドレスに受け取ったオフセットを加算して、逆参照されるintメンバーを見つけます。

それはコンパイラが、それはコンパイラは、ポインタの種類を知っている場合は、常に、ポインタを調整し、ポインタ型は実行時まで知られていない方法がないだけのことですか?

実行時までわかっていないポインタ型はありません。すべての変数は、コンパイル時に既知の型を持ちます。 (多態性はデータメンバーへのポインタで直接的には作用しません。)

+0

'int Derived * ::'から 'int Base * ::'への逆変換のように思えるでしょうか? (私はこの質問を見るまでこの言語機能を完全に知らなかったので、その質問が意味をなさないならば私には容赦してください) –

+2

@KyleStrand 'int Derived :: *'から 'int Base :: *'への変換は明示的キャストによってのみ許可され、オブジェクト内に実際に存在しないメンバーにアクセスするために使用される場合、未定義の動作につながる可能性があります。 – aschepler

+1

これは意味があります。 (私は一般的に、明示的なキャストはすべて強力であり、無意味な変換を達成できると仮定しているため、「決して」という言葉を強調してはいけないはずです。)ありがとう。 –

関連する問題