【发布时间】:2021-01-22 06:29:51
【问题描述】:
我试图了解何时可以通过指向 void 的指针安全地将派生对象转换为基本子对象(我认为它应该与 reinterpret_cast 相同)。但是我能找到的标准对此的措辞让我感到困惑。首先,
如果满足以下条件,两个对象 a 和 b 是指针可互转换的:
——一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的第一个基类子对象
由此无法得出可靠的结论,“or”是适用于“or”之前的整个子句还是仅适用于它的第二部分。这很重要,因为我无法确定在没有非静态数据成员的情况下,“标准布局类对象”是否对于与基本子对象的指针互转换是必要的。
但在进一步挖掘标准时,我发现:
如果标准布局类对象有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同。否则,它的地址与其第一个基类子对象的地址相同(如果有的话)。
这似乎更清楚地表明需要“标准布局”。但仍然令人困惑。考虑以下代码:
class B { public: int b; };
class C : public B { public: int c; };
int main ()
{
C c;
B* b = &c;
std::cout << &c << " address of standard-layout class object\n";
std::cout << &c.c << " address of its first non-static data member\n";
std::cout << b << " address of first base class subobject\n";
return 0;
}
在 VS2019 上,结果是:
009BFBF8 address of standard-layout class object
009BFBFC address of its first non-static data member
009BFBF8 address of first base class subobject
这不是标准所说的。你能解释一下吗?
【问题讨论】:
-
对于这两个报价标准布局是一个前提。当我在这里尝试时,看起来
C不是标准布局:godbolt.org/z/3W796T -
@idclev,在 VS 上它还提供
false。但是在从 B 或 C 中删除一个成员后,它会解析为true。 -
在
C是标准布局的情况下,你能得到你所期望的吗? -
C 不是标准布局类,因此第二段没有说明您的示例。
-
顺便说一句,你的动机有点不清楚。你不需要
reinterpret_cast也不需要绕道void*在基础和派生之间转换
标签: c++ class inheritance casting standards