簡単な答え:未定義の動作は含まれていません。表示される動作は次のとおりです。
- この式
&A::aは、クラスAのメンバーaを指すメンバーへのポインターを取得しようとします。aがAで保護されている場合、この式はクラスA(またはAの友達)内のアクセスチェックにのみ合格します。Aから派生したクラスBでは、式を介してのみメンバーへの同じポインターを取得できます&B::a(この式のタイプは引き続きであることに注意してくださいint A::*)。それで:
A::aAで保護されている場合、式&A::aは派生クラスBのメンバー関数で許可されていません。これはコンパイラエラーです。
- Aでpublicの場合
A::a、この式は有効であり、memeberへのポインターを生成します。
- メンバーへのポインタをにストリーミングする
ostream、たとえばを使用cout << &A::aすると、が出力されます1。これは、を呼び出した結果ostream::operator << (bool)です。boolalphaマニピュレータを使用して、これが実際に選択されたオーバーロードであることを確認できcout << boolalpha << &A::aますtrue。
- 変更された式&(A :: a)または単に&aを使用する場合、メンバーへのポインターは形成されません。ここでは、現在のオブジェクトのメンバーaのアドレス(つまり、と同じ
&(this->a))が取得されます。これは、intへの通常のポインターです。の基本クラスサブオブジェクトの保護されたメンバーへのこのアクセス*thisは有効であるため、aがAで保護されている場合でもバリアントを使用できます。
より長い説明:
標準によると(5.3.1 / 3):
単項&演算子の結果は、そのオペランドへのポインターです。オペランドは左辺値または修飾IDでなければなりません。オペランドが、タイプTのクラスCの非静的メンバーmに名前を付ける修飾IDである場合、結果はタイプ「タイプTのクラスCのメンバーへのポインター」を持ち、C::mを指定するprvalueになります。[...]
したがって、式&A::aはクラスAのメンバーaへのメンバーへのポインターを取得しようとします。
次の段落(5.3.1 / 4)では、&X ::m構文のみがメンバーへのポインターを生成することを詳しく説明してい&(X::m)ます。&mX::m
メンバーへのポインターは、明示的な&が使用され、そのオペランドが括弧で囲まれていない修飾IDである場合にのみ形成されます。
ただし、このような式は、アクセスが許可されている場合にのみ有効です。保護されたメンバー(11.4 / 1)の場合:
非静的データメンバーまたは非静的メンバー関数がそのネーミングクラスの保護されたメンバーである場合、第11項で説明したもの以外の追加のアクセスチェックが適用されます(11.2)前述のように、保護されたメンバーへのアクセスは、参照は、あるクラスCの友人またはメンバーで発生します。アクセスがメンバー(5.3.1)へのポインターを形成する場合、ネストされた名前指定子は、CまたはCから派生したクラスを示します。[...]
あなたの場合、保護されたメンバーaへのアクセスが許可されます。これは、aへの参照がAから派生したクラスBのメンバーで発生するためです。式がメンバーへのポインターを形成しようとすると、ネストされた名前指定子(一部最後の"::a")の前はBを表す必要があります。したがって、許可される最も単純な形式は&B::aです。このフォーム&A::aは、クラスA自体のメンバーまたは友人内でのみ許可されます。
メンバーへのポインター用のフォーマットされた出力演算子(istreamメンバーとしてもfree演算子関数としても)がないため、コンパイラーは、標準の変換(シーケンス)を使用して呼び出すことができるオーバーロードを調べます。ポインタからメンバー、他の何かへの唯一の標準的な変換は、4.12/1で説明されています。
メンバー型への[...]ポインタのprvalueは、bool型のprvalueに変換できます。[...]nullメンバーポインタ値はfalseに変換されます。その他の値はすべてtrueに変換されます。[...]
この変換は、を呼び出すための追加の変換なしで使用できますbasic_ostream<charT,traits>& basic_ostream<charT,traits>::operator<<(bool n)。他のオーバーロードはより長い変換シーケンスを必要とするため、オーバーロードが最適です。
一部のメンバーのアドレスを取得するため、これ&A::aはnullメンバーポインター値ではありません。したがって、に変換されtrue、「1」(noboolalpha)または「true」(boolalpha)として出力されます。
最後に、&(A::a)aがAで保護されている場合でも、式はBのメンバーで有効です。上記の規則によってこの式はメンバーへのポインターを形成しないため、上記で引用した特別なアクセス規則は適用されません。このような場合、11.4/1は続きます。
他のすべてのアクセスには、(おそらく暗黙の)オブジェクト式(5.2.5)が含まれます。この場合、オブジェクト式のクラスはCまたはCから派生したクラスでなければなりません。
ここで、オブジェクトの印象は暗黙的です。(*this)つまりA::a、と同じ意味(*this).A::aです。のタイプは(*this)明らかにアクセスが発生するクラス(B)と同じであるため、アクセスが許可されます。[注:int x = A(42).aB内では許可されません。]
つまり、 &(A::a)withinB::show()はと同じ意味で&(this->a)あり、それはintへの単純なポインタです。