【发布时间】:2011-11-02 11:30:17
【问题描述】:
在不可修改的标头中声明了一个前向 C 结构。我想“虚拟地”向它添加便利的成员函数。显然,我的第一选择是扩展结构并将方法添加到派生类。不能做,因为结构本身在标题中被声明为“转发”,所以我收到错误“错误:不完整类型的无效使用......”。如果我尝试使用旧结构的单个元素定义新结构,我会收到类似的错误。这很糟糕。
但是,我想我可以用 reinterpret_cast 做一些hacky 来让它正常工作。它的方式是这样的:
//defined in header
struct A forward;
void do_something_with_A(A* a, int arg);
//defined in my wrapper
struct B {
B* wrap(A* a) {return reinterpret_cast<B*>(a); }
void do_something(int arg) {do_something_with_A(reinterpret_cast<A*>(this),arg); }
}
如果我添加了从 B 类型到 A 类型的隐式转换,我认为这可以几乎将 B 视为 A 的零数据继承者。但是,这显然会带来问题:这在 C++ 中是未定义的吗?通常我会认为访问非法转换的结构的元素是未定义的;这就说得通了。但是,我认为从一种类型到另一种类型的 reinterpret_casting,传递该指针,然后再次转换,中间不做任何非法的事情就可以了。我还认为编译器实现非虚拟结构成员的方式是创建一个函数
B::do_something(B* b, int arg)
并使用 B 的适当参数调用它。然后这会简化为前一种情况,根据我的可疑逻辑,这是可以的。所以我认为在一个实际上是 reinterpret_cast A 的结构上调用 .do_something 是可以的。
然而,这并没有说明 C++ 标准在这个问题上的实际说法。有什么帮助吗?此外,如果有人知道这在实际工作中的效果如何(即“每个编译器都接受这个”,或“这仅适用于少数编译器”),这也会有所帮助,但效果稍差。
【问题讨论】:
-
这里不能使用
static_cast,除非在B类中添加相关转换,即采用A*的构造函数。无论如何,A指针不携带任何信息,这意味着它没有任何价值。否则它会携带一些信息,在这种情况下,您将进入reinterpret_cast和 UB 领域,对于您的编译器来说可能还可以,也许不是。 -
另外,我相信在 C++
structs 中没有数据成员的大小仍然为 1。 -
抱歉,我对 reinterpret_cast 与静态演员的混淆混淆了这个问题。我会更新问题。
-
"Premature optimization is the root of all evil" - Donald Knuth.
-
如果您正在编写其他人会使用的代码,您不想过早地阻止他们永远优化。
标签: c++ struct reinterpret-cast