将指向数据成员的指针转换为void *

时间:2013-03-21 12:17:26

标签: c++ casting type-conversion pointer-to-member

我知道我可以获取指向类或结构的数据成员的指针,但以下代码的最后一行无法编译:

struct abc
{
    int a;
    int b;
    char c;
};

int main()
{
    typedef struct abc abc;
    char abc::*ptt1 = &abc::c;
    void *another_ptr = (void*)ptt1;
}

为什么我不能将ptt1转换为another_ptr?我们正在讨论指针,因此一个指针应该具有与另一个指针类似的维度(尽管在概念上不同)

3 个答案:

答案 0 :(得分:10)

指向非静态类成员类型的指针对象指针类型不同;他们表现得非常不同。实际上,您甚至无法取消引用*成员的指针。要通过指向成员的指针访问成员,请改用.*->*运算符。如果你可以将它强制转换为这样的对象指针类型,那么,如果你用*取消引用它会发生什么?

只有对象指针类型具有标准转换为void*(§4.10):

  

类型为“指向 cv T的指针的prvalue”,其中T是对象类型,可以转换为“指向的指针的prvalue” cv void“。

它们是如此不同以至于标准甚至不顾一切地确保术语“指针”不包含指向非静态成员的指针(§3.9.2):

  

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

答案 1 :(得分:2)

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

更一般地说,char*只能包含指向数据的指针。 它必须与最大的数据指针一样大(通常 一个{{1}}),但指向函数和成员指针的指针可以 更大,不适合(几乎指向成员函数的指针) 从不适合)。

答案 2 :(得分:0)

你想做这样的事吗?

struct ABC
{
    int a;
    int b;
    char c;
};

int main()
{
    ABC abc;
    char *ptt1 = &abc.c;
    void *another_ptr = (void*)ptt1;
}