6

クラスまたは構造体のデータ メンバーへのポインターを取得できることはわかっていますが、次のコードの最後の行はコンパイルに失敗します。

struct abc
{
    int a;
    int b;
    char c;
};

int main()
{
    char abc::*ptt1 = &abc::c;
    void *another_ptr = (void*)ptt1;
}

ptt1 を another_ptr に変換できないのはなぜですか? ポインターについて話しているので、あるポインターは別のポインターと同様の次元を持つ必要があります (概念的には異なりますが)。

4

3 に答える 3

10

非静的クラス メンバ型へのポインタは、オブジェクト ポインタ型と同じではありません。彼らは非常に異なった振る舞いをします。実際、 を使用してメンバーへのポインターを逆参照することさえできません*。メンバーへのポインターを介してメンバーにアクセスするには、代わりに.*and->*演算子を使用します。このようにオブジェクト ポインター型にキャストできた場合、それを逆参照するとどうなるでしょう*か。

void*(§4.10)への標準変換があるのは、オブジェクト ポインター型のみです。

「 cv へのポインター」型 ( はオブジェクト型) の prvalue はT、「cvTへのポインター」型の prvalue に変換できます。 void

それらは非常に異なっているため、「ポインター」という用語に非静的メンバーへのポインターが含まれていないことを確認するために標準が邪魔をすることさえあります (§3.9.2):

静的メンバーへのポインターを除いて、「ポインター」を参照するテキストは、メンバーへのポインターには適用されません。

于 2013-03-21T12:22:07.570 に答える
2

主な理由は、メンバーへのポインターがデータへのポインターと同じサイズと表現を持つ必要がないためです。 実際には、データ メンバーへのポインターが に収まらないことを想像するのは困難です。これは、データ メンバーへvoid*のポインターが実際にはオフセットを含む必要があるだけだからです。大まかに言えば、データ メンバーへのポインターは より大きくする必要はなくsize_tvoid*少なくとも は と同じ大きさでなければなりませんsize_t。一方、ポインタでは正当でないビットパターンを簡単に含めることができます。 実際、Steve Jessop が指摘しているように、メンバーへのポインターには追加情報が必要です。これは、メンバーが仮想ベースにある場合、そのオフセットは最も派生したクラスに依存し、ポインターの追加情報に基づいて動的に計算する必要があるためです。

より一般的には、avoid*にはデータへのポインターのみを含めることができます。これは、最大のデータ ポインター (通常はchar*) と同じ大きさでなければなりませんが、関数へのポインターとメンバー ポインターは、より大きくなり、収まらない場合があります (メンバー関数へのポインターはほとんど収まりません)。

于 2013-03-21T12:37:28.473 に答える
0

このようなことをしようとしていますか?

struct ABC
{
    int a;
    int b;
    char c;
};

int main()
{
    ABC abc;
    char *ptt1 = &abc.c;
    void *another_ptr = (void*)ptt1;
}
于 2013-03-21T12:28:36.127 に答える