指向成员变量的多态指针

Polymorphic pointer to member variables

本文关键字:多态 指针 变量 成员      更新时间:2023-10-16

我正试图以多态的方式使用指向成员变量的指针。

这项工作:

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::*'

有没有办法做到这一点,即将成员指针"向上投射"到它的基类?

这是不可能的。由于多重继承,基的地址并不总是和派生的地址相同。你需要一些隐藏的地址调整魔法来将一个地址转换为另一个地址,而一个指向成员的指针,作为一个非常简单的对象(基本上是一个整数偏移量(无法适应这种魔法。

的确,地址调整只是有时需要,当不需要时,原则上可以允许指向成员的多态指针。但为了简单和一致性,这并没有完成。

您可以使用指向接受Foo*并返回BaseClass*的函数(或类似函数的对象(的指针,而不是指向成员的指针。不过,您必须为每个成员创建一个单独的函数。

BaseClass* getMember(const int i)
{
  switch(i)
  {
  case 0: return &member0;
  case 1: return &member1;
  default: throw <exception>;
  }
}

为了鲁棒性,您必须检查i是否在0和1的范围内;所以你可以考虑这个简化的方法。

更简单的方法是完全跳过成员数据指针。

getMember(int i) {
    BaseClass* ptr[2] = { &member0, &member1 };
    return ptr[i];
}