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 T的指针”类型的纯右值,其中T是对象类型,可以转换为“指向cv void的指针”类型的纯右值。

它们是如此不同,以至于标准甚至不遗余力地确保术语“指针”不包括指向非静态成员的指针(第 3.9.2 节):

除了指向静态成员的指针外,引用“指针”的文本不适用于指向成员的指针。

于 2013-03-21T12:22:07.570 回答
2

主要原因是因为没有要求指向成员的指针与指向数据的指针具有相同的大小和表示形式。 在实践中,很难想象指向数据成员的指针无法放入 avoid*中,因为指向数据成员的指针实际上只需要包含偏移量。粗略地说,指向数据成员的指针永远不需要大于 a size_t,并且 avoid*必须至少与 a 一样大size_t。另一方面,它很容易包含在指针中不合法的位模式。 事实上,正如 Steve Jessop 所指出的,指向成员的指针确实需要额外的信息,因为如果成员在虚拟基中,它的偏移量取决于最派生的类,并且必须根据指针中的额外信息动态计算。

更一般地说,avoid*只能包含指向数据的指针。它必须与最大的数据指针(通常是 a 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 回答