1

ポリモーフィックな方法でメンバー変数へのポインターを使用しようとしています。

これは機能します:

struct Foo
{
   int member0;
   int member1;

   int* getMember( int i )
   {
     static int Foo::* table[2] = { &Foo::member0, &Foo::member1 };
     return &( this->*table[i] );
   }
};

メンバーは同じタイプ(BaseClass)ではないため、これは行われません。

struct Foo
{
   SubClassA member0;
   SubClassB member1;

   BaseClass* getMember( int i )
   {
     static BaseClass Foo::* table[2] = { &Foo::member0, &Foo::member1 };
     return &( this->*table[i] );
   }
};

g++によって報告されるエラーは次のとおりです。

[...] invalid conversion from 'SubClassA Foo::*' to 'BaseClass Foo::*'
[...] invalid conversion from 'SubClassB Foo::*' to 'BaseClass Foo::*'

これを機能させる方法、つまり、メンバーポインタをその基本クラスに「アップキャスト」する方法はありますか?

4

3 に答える 3

1

これは不可能です。多重継承のため、ベースのアドレスは派生アドレスと常に同じではありません。あるアドレスを別のアドレスに変換するには、隠しアドレス調整の魔法が必要です。メンバーへのポインタは、非常に単純なオブジェクト(基本的に整数オフセット)であるため、この魔法に対応できません。

確かに、アドレス調整が必要なのはたまにしかなく、必要がない場合は、原則としてメンバーへの多態的なポインタを許可することができます。しかし、単純さと一貫性のために、これは行われません。

メンバーへのポインターの代わりに、Foo*を受け入れてBaseClass*を返す関数(または関数のようなオブジェクト)へのポインターを使用できます。ただし、メンバーごとに個別の関数を作成する必要があります。

于 2011-08-16T19:20:28.553 に答える
1
BaseClass* getMember(const int i)
{
  switch(i)
  {
  case 0: return &member0;
  case 1: return &member1;
  default: throw <exception>;
  }
}

堅牢性を確保するには、とにかくiが範囲内か0と1の範囲内にあるかを確認する必要があります。したがって、この単純化されたアプローチについて考えることができます。

于 2011-08-16T16:39:36.150 に答える
0

これを行う簡単な方法は、メンバーデータポインタを完全にスキップすることです。

getMember(int i) {
    BaseClass* ptr[2] = { &member0, &member1 };
    return ptr[i];
}
于 2011-08-16T16:29:31.970 に答える