tow*_*owi 7 c++ pointers casting multiple-inheritance language-lawyer
我知道,通过多重继承,允许指针的值改变.但这也是单继承的情况吗?或者POD类型是什么?
你可能知道经典的例子:
#include <iostream>
using std::cout;
struct Base1 { virtual void f1() {} };
struct Base2 { virtual void f2() {} };
struct Derived : public Base1, public Base2 { virtual void g() {} };
int main() {
Derived d{};
auto *pd = &d;
auto pb1 = (Base1*)pd;
auto pb2 = (Base2*)pd;
cout << pd << "\n"; // say, 0x1000
cout << pb1 << "\n"; // say, 0x1000
cout << pb2 << "\n"; // say, 0x1008 !!!
}
Run Code Online (Sandbox Code Playgroud)
到目前为止这么好,这是很好的旧编译器实践.对象的布局方式是"根" Base2具有Derived可在打印实际指针值时打印的偏移量.这不是一个问题,当避免做void*和reinterpret_casts.
据我所知,实际上只有多重继承.
但我的问题是:标准对"演员期间指针改变值"的评价是什么?这种情况只能通过多重继承发生,还是单继承或者投射POD也会发生?
如果类型是标准布局,则任何继承级别上指向包含结构的指针都等于指向第一个元素的指针。通过传递性,指向所有继承级别的指针也是相同的——并且标准继续前进,并且在不存在非静态数据成员的奇怪情况下也做出了这种保证。
\n(请注意,为了成为标准布局,类型只能在继承图中的一层引入数据成员——其他子类可以添加功能并保持标准布局,但不能添加更多数据)。
\n如果类型不是标准布局,则无法做出任何保证,并且您必须使用static_cast, not reinterpret_cast(也不能使用 reinterpret_cast 等效项,例如多个 static_cast withvoid*作为中间值)来正确包含任何偏移量。
所有POD类型当然都是标准布局,POD性要求标准布局和琐碎性。
\n我解释的确切规则可以在第 9.2 节中找到:
\n\n\n如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同。否则,其地址与其第一个基类子对象(如果有)的地址相同。
\n[ 注意:因此,标准布局结构对象内可能存在未命名的填充,但在其开头则不然,这是实现适当对齐所必需的。\xe2\x80\x94 尾注]
\n[ 注意:该对象及其第一个子对象是指针可相互转换的。\xe2\x80\x94 尾注]
\n
第 10 节明确指出非标准布局类型可以使用奇怪的布局:
\n\n\n基类子对象在最派生对象中分配的顺序未指定。
\n