我有一个指向派生类的指针表。该程序使用许多使用这些表中的条目的小类。定期地,必须交换所有这些小类,目的是它们使用表中不同类的数据,但它们仅使用基类数据。所以那些小类使用指向表条目的指针,但这些指针实际上是指向基类指针的指针。孤立地,就是这样,下面的工作在gcc 4.8.2中(真实的东西有复杂的类;这只是一个例子)
#include <iostream>
class Base {public: int i;};
class Derived : public Base {public: int j;};
int main() {
Base **b;
Derived *table[2];
table[0] = new Derived; table[0]->i = 1; table[0]->j = -2;
table[1] = new Derived; table[1]->i = 4; table[1]->j = -5;
b = reinterpret_cast<Base**>(&(table[0]));
std::cout << "first: " << (**b).i << " " << "\n";
b = reinterpret_cast<Base**>(&(table[1]));
std::cout << "second: " << (**b).i << " " << "\n";
{Derived *temp; temp = table[0]; table[0] = table[1]; table[1] = temp;}
b = reinterpret_cast<Base**>(&(table[0]));
std::cout << "first switched: " << (**b).i << " " << "\n";
b = reinterpret_cast<Base**>(&(table[1]));
std::cout << "second switched: " << (**b).i << " " << "\n";
}
表无法被破坏:它总是包含完全相同的派生类类型的指针,因此理论上它们都可以被交换。使用该表的类将只使用基类数据。如果reinterpret_cast
被dynamic_cast
或static_cast
替换,则编译器会抱怨。现在,这一切都很好,除了这样的警告:“......在大多数情况下导致代码是系统特定的,因此是不可移植的”,以及其他真正可怕且严厉的陈述,由明确知道的自以为是的专家很多。
以上是否合理安全地使用了reinterpret_cast?
答案 0 :(得分:4)
既不安全也不合理。
首先有点咆哮。 reinterpret_cast
是一个广泛的选择。最后的武器。这不安全。这不友好。它不会保护你自己。它不应该是你选择的首选工具。如果reinterpret_cast
没有“工作”并且您不理解编译器告诉您的内容,那么您不应该只在那里发出static_cast
。相反,您应该首先尝试理解编译器的错误消息,然后修复实际问题。
咆哮结束。现在你的情况:
b = reinterpret_cast<Base**>(&(table[0]));
table
是指向Derived
的指针数组。因此,您试图从指向指针 - Derived
转换为指向指针指针 - Base
。您应该做的是将指针指向Derived
指针指向 - Base
,如下所示:
Base* b = static_cast<Base*>(table[0]);
然后使用它:
std::cout << "first: " << (*b).i << " " << "\n";
但由于Derived
是Base
的直接后代,因此您甚至不需要显式强制转换。这样可以正常工作:
Base* b = table [0];
更好的是,既然你真的不需要指针,为什么不只是抓住一个引用呢?
Base& b = *table[0];
std::cout << "first: " << b.i << " " << "\n";