我正在尝试以多态方式使用指向成员变量的指针。
这有效:
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::*'
有没有办法让这项工作,即“向上转发”指向其基类的成员指针?
答案 0 :(得分:1)
BaseClass* getMember(const int i)
{
switch(i)
{
case 0: return &member0;
case 1: return &member1;
default: throw <exception>;
}
}
为了获得稳健性,您必须检查i
是否在范围内或0和1之间;所以你可以考虑这种简化的方法。
答案 1 :(得分:1)
这是不可能的。由于多重继承,base-of-base并不总是与derived-of-derived相同。你需要一些隐藏的地址调整魔法来将一个转换为另一个,并且指向成员的指针是一个非常简单的对象(基本上是一个整数偏移)不能容纳这种魔法。
确实有时只需要地址调整,并且当不需要时,原则上可以允许多态指向成员。但为了简单和一致,这还没有完成。
而不是指向成员的指针,您可以使用指向接受Foo *并返回BaseClass *的函数(或类似函数的对象)的指针。您必须为每个成员创建一个单独的函数。
答案 2 :(得分:0)
更简单的方法是完全跳过成员数据指针。
getMember(int i) {
BaseClass* ptr[2] = { &member0, &member1 };
return ptr[i];
}