指向成员变量的多态指针

发布于 2024-11-30 09:15:08 字数 789 浏览 1 评论 0原文

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

这有效:

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

有没有办法使这项工作有效,即将成员指针“向上转换”到其基类?

I'm trying to use pointers to member variables in a polymorphic fashion.

This works:

struct Foo
{
   int member0;
   int member1;

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

This does not, since the members are not of the same type (BaseClass):

struct Foo
{
   SubClassA member0;
   SubClassB member1;

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

The error reported by g++ is:

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

Is there a way to make this work, ie to "upcast" the member pointer to its base class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笑梦风尘 2024-12-07 09:15:08

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

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

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

This is not possible. Because of multiple inheritance, address-of-base is not always the same as address-of-derived. You need some hidden address adjustment magic to convert one to the other, and a pointer-to-member, being a very simple object (basically an integer offset) cannot accomodate this magic.

It is true that address adjustment only needed sometimes, and when it is not needed, polymorphic pointers-to-members could in principle be allowed. But this is not done, for simplicity and consistency.

Instead of pointers-to-members, you can use pointers to functions (or function-like objects) that accept a Foo* and return a BaseClass*. You will have to make a separate function for each member though.

贪了杯 2024-12-07 09:15:08
BaseClass* getMember(const int i)
{
  switch(i)
  {
  case 0: return &member0;
  case 1: return &member1;
  default: throw <exception>;
  }
}

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

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

For robustness you have to anyway check if the i is within the range or 0 and 1; so you can think for this simplified approach.

夏日落 2024-12-07 09:15:08

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

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

The easier way to do it would be to skip the member data pointers altogether.

getMember(int i) {
    BaseClass* ptr[2] = { &member0, &member1 };
    return ptr[i];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文