C++03 std、§4.11 2 メンバー変換へのポインター:
「 cv T型の B のメンバーへのポインター」型の右辺値 ( B はクラス型) は、「 cv T 型の D のメンバーへのポインター」型の右辺値 (D は派生クラス)に変換できます( B の 10 節)。 B が D のアクセス不可能 (11 節)、あいまい (10.2) または仮想 (10.1) 基本クラスである場合、この変換を必要とするプログラムは形式が正しくありません。変換の結果は、変換前のメンバーへのポインターと同じメンバーを参照しますが、基底クラスのメンバーを派生クラスのメンバーであるかのように参照します。結果は、B の D のインスタンスのメンバーを参照します。結果の型は「cv型の D のメンバーへのポインター」であるため、T」である場合、D オブジェクトで逆参照できます。結果は、B のメンバーへのポインターが D の B サブオブジェクトで逆参照された場合と同じになります。null メンバー ポインター値は、変換先の型の null メンバー ポインター値に変換されます。52)
52)メンバーへのポインターの変換の規則 (基底のメンバーへのポインターから派生のメンバーへのポインターへ) は、オブジェクトへのポインターの規則 (ポインターから派生へのポインターから基底へのポインターへ) と比べて逆になっているように見えます (4.10、節 10)。 . この反転は、型の安全性を確保するために必要です。メンバーへのポインターは、オブジェクトへのポインターまたは関数へのポインターではなく、そのようなポインターの変換規則はメンバーへのポインターには適用されないことに注意してください。特に、メンバーへのポインターは void* に変換できません。
つまり、メンバーがあいまいでない限り、アクセス可能な非仮想基本クラスのメンバーへのポインターを、派生クラスのメンバーへのポインターに変換できます。
class A {
public:
void foo();
};
class B : public A {};
class C {
public:
void bar();
};
class D {
public:
void baz();
};
class E : public A, public B, private C, public virtual D {
public:
typedef void (E::*member)();
};
class F:public E {
public:
void bam();
};
...
int main() {
E::member mbr;
mbr = &A::foo; // invalid: ambiguous; E's A or B's A?
mbr = &C::bar; // invalid: C is private
mbr = &D::baz; // invalid: D is virtual
mbr = &F::bam; // invalid: conversion isn't defined by the standard
...
他の方向への変換 ( 経由static_cast
) は、§ 5.2.9 9 によって管理されます。
「 cv1 T型の D のメンバーへのポインター」型の右辺値は、「 cv2 T型の B のメンバーへのポインター」型の右辺値に変換できます。ここで、B は D の基本クラス ( 10 節の class.derived ) です。 、「T 型の B のメンバーへのポインター」から「T 型の D のメンバーへのポインター」への有効な標準変換が存在し ( 4.11 conv.mem )、cv2が cv- と同じかそれ以上の cv-qualification である場合資格より、cv1 . 11) null メンバポインタ値 ( 4.11 conv.mem) は、変換先の型の null メンバー ポインター値に変換されます。クラス B が元のメンバーを含む場合、または元のメンバーを含むクラスの基本クラスまたは派生クラスである場合、メンバーへの結果のポインターは元のメンバーを指します。それ以外の場合、キャストの結果は未定義です。[注: クラス B には元のメンバーが含まれる必要はありませんが、メンバーへのポインターが逆参照されるオブジェクトの動的型には元のメンバーが含まれている必要があります。5.5 expr.mptr.operを参照してください。]
11)関数型 (メンバ関数型へのポインタで使用されるものを含む) は決して cv 修飾されません。8.3.5 dcl.fctを参照してください。
つまり、 a からa に変換できる場合は、派生物D::*
からベースに変換できますが、タイプ D のオブジェクトまたは D の子孫である on オブジェクトのみを使用できます。B::*
B::*
D::*
B::*