【问题标题】:Convert pointer to data member to void *将指向数据成员的指针转换为 void *
【发布时间】:2013-03-10 22:47:43
【问题描述】:

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

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

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

为什么我不能将 ptt1 转换为 another_ptr?我们说的是指针,所以一个指针应该与另一个指针具有相似的维度(尽管在概念上有所不同)?

【问题讨论】:

  • 错误信息是什么?
  • 我正在使用 MSVC2012:错误 C2440:'type cast':无法从 'char abc::*' 转换为 'void *'
  • 不要在 c++ 中使用 c-casts。坚持使用 c++ 强制转换(在本例中为 reinterpret_cast)。
  • @RedX:但是在您知道它是哪种转换之前,您不能选择 C++ 转换。在这种情况下,您无法知道它是哪种转换,因为没有任何类型的转换可用:-)

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


【解决方案1】:

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

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

【讨论】:

  • “指向数据成员的指针实际上只需要包含一个偏移量” - 除非该成员位于虚拟基类中,在这种情况下需要更多(我想。我错了吗?只有指向成员函数的指针很难?)。
  • @SteveJessop 你是对的。我不知道我在哪里看到它以简单的偏移量呈现。使用 VC 2012,32 位模式,int* 的大小为 4,int Class::* 12。(仔细想想,我想我最后一次真正详细查看它是在添加多重继承之前语言。然后,唯一的困难是虚函数。)
【解决方案2】:

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

只有对象指针类型可以标准转换为void*(第 4.10 节):

“指向 cv T 的指针”类型的纯右值,其中 T 是对象类型,可以转换为“指向 cv的指针”类型的纯右值> void".

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

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

【讨论】:

  • 关于void* 唯一能做的就是将其转换回原始类型,因此可能使用的问题不一定有效。您也不能用* 取消引用void*
  • 除了仍然不清楚您所说的“普通指针”是什么意思。只有指向对象的指针(在 C++ 意义上)可以转换为void*。指向成员的指针和指向函数的指针不能。
  • @JamesKanze 好的,我现在使用标准术语。
【解决方案3】:

您是否正在尝试做这样的事情?

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

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

【讨论】:

  • 没有对象就毫无意义。
  • 这是一个非常夸张的类比:您尝试的就像是试图将钉子钉在房子的蓝图上,而不是房子本身。
猜你喜欢
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多